add cookie parser, finish callback & add login and whoami
This commit is contained in:
3
index.js
3
index.js
@@ -2,6 +2,8 @@ import * as fs from 'fs'
|
|||||||
import { execSync } from 'child_process'
|
import { execSync } from 'child_process'
|
||||||
import postgres from 'postgres'
|
import postgres from 'postgres'
|
||||||
import express, { json } from 'express'
|
import express, { json } from 'express'
|
||||||
|
import cookieParser from 'cookie-parser'
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
|
|
||||||
if (!process.env.DATABASE_URI) {
|
if (!process.env.DATABASE_URI) {
|
||||||
@@ -24,6 +26,7 @@ export { app, fs, db, globalConfig, globalVersion }
|
|||||||
|
|
||||||
app.use(json()) // Allows receiving JSON bodies
|
app.use(json()) // Allows receiving JSON bodies
|
||||||
// see important note: https://expressjs.com/en/api.html#express.json
|
// see important note: https://expressjs.com/en/api.html#express.json
|
||||||
|
app.use(cookieParser()) // Allows receiving cookies
|
||||||
|
|
||||||
process.on('SIGTERM', function() {
|
process.on('SIGTERM', function() {
|
||||||
console.log("Received SIGTERM, exiting...")
|
console.log("Received SIGTERM, exiting...")
|
||||||
|
|||||||
23
package-lock.json
generated
23
package-lock.json
generated
@@ -9,6 +9,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"cookie-parser": "^1.4.7",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"marked": "^14.1.3",
|
"marked": "^14.1.3",
|
||||||
"nodemailer": "^6.9.15",
|
"nodemailer": "^6.9.15",
|
||||||
@@ -158,6 +159,28 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cookie-parser": {
|
||||||
|
"version": "1.4.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
|
||||||
|
"integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": "0.7.2",
|
||||||
|
"cookie-signature": "1.0.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cookie-parser/node_modules/cookie": {
|
||||||
|
"version": "0.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
|
||||||
|
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cookie-signature": {
|
"node_modules/cookie-signature": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"cookie-parser": "^1.4.7",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"marked": "^14.1.3",
|
"marked": "^14.1.3",
|
||||||
"nodemailer": "^6.9.15",
|
"nodemailer": "^6.9.15",
|
||||||
|
|||||||
@@ -4,11 +4,37 @@ import { logRequest } from "../liberals/logging.js"
|
|||||||
import { randomStringBase62, getHumanReadableUserAgent } from "../liberals/misc.js"
|
import { randomStringBase62, getHumanReadableUserAgent } from "../liberals/misc.js"
|
||||||
|
|
||||||
app.get("/api/auth/whoami", (rreq,rres) => {
|
app.get("/api/auth/whoami", (rreq,rres) => {
|
||||||
rres.send("Non functional endpoint")
|
if (!rreq.cookies["APIToken"] && !rreq.get("Authorization")) {
|
||||||
|
rres.send({ "loggedIn": false, "username": "", "scopes": "" })
|
||||||
|
} else {
|
||||||
|
db`select s.scopes, u.username from sessions s join users u on s.owner = u.id where s.token = ${rreq.cookies["APIToken"] ?? rreq.get("Authorization")}`.then(dbRes => {
|
||||||
|
if (dbRes.length > 0 && dbRes.length < 2) {
|
||||||
|
rres.send({ "loggedIn": true, "username": dbRes[0]?.username, "scopes": dbRes[0]?.scopes.split(",") })
|
||||||
|
} else {
|
||||||
|
rres.send({ "loggedIn": false, "username": "", "scopes": "" })
|
||||||
|
}
|
||||||
|
}).catch(dbErr => {
|
||||||
|
logRequest(rres,rreq,500,dbErr)
|
||||||
|
rres.status(500).send({ "loggedIn": false, "username": "", "scopes": "" })
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get("/api/auth/login", (rreq,rres) => {
|
app.get("/api/auth/login", (rreq,rres) => {
|
||||||
rres.redirect(`${globalConfig.oidc.authorizeUrl}?client_id=${globalConfig.oidc.clientId}&response_type=code&scope=openid enstrayedapi&redirect_uri=${rreq.protocol}://${rreq.get("Host")}/api/auth/callback`)
|
|
||||||
|
if (rreq.query.state === "redirect") {
|
||||||
|
if (!rreq.query.destination) {
|
||||||
|
rres.redirect(`${globalConfig.oidc.authorizeUrl}?client_id=${globalConfig.oidc.clientId}&response_type=code&scope=openid enstrayedapi&redirect_uri=${rreq.protocol}://${rreq.get("Host")}/api/auth/callback&state=none`)
|
||||||
|
} else {
|
||||||
|
let newState = `redirect_${btoa(rreq.query.destination).replace("/","-")}`
|
||||||
|
rres.redirect(`${globalConfig.oidc.authorizeUrl}?client_id=${globalConfig.oidc.clientId}&response_type=code&scope=openid enstrayedapi&redirect_uri=${rreq.protocol}://${rreq.get("Host")}/api/auth/callback&state=${newState}`)
|
||||||
|
}
|
||||||
|
} else if (rreq.query.state === "display" || rreq.query.state === "close") {
|
||||||
|
rres.redirect(`${globalConfig.oidc.authorizeUrl}?client_id=${globalConfig.oidc.clientId}&response_type=code&scope=openid enstrayedapi&redirect_uri=${rreq.protocol}://${rreq.get("Host")}/api/auth/callback&state=${rreq.query.state}`)
|
||||||
|
} else {
|
||||||
|
rres.redirect(`${globalConfig.oidc.authorizeUrl}?client_id=${globalConfig.oidc.clientId}&response_type=code&scope=openid enstrayedapi&redirect_uri=${rreq.protocol}://${rreq.get("Host")}/api/auth/callback&state=none`)
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get("/api/auth/callback", (rreq,rres) => {
|
app.get("/api/auth/callback", (rreq,rres) => {
|
||||||
@@ -31,11 +57,23 @@ app.get("/api/auth/callback", (rreq,rres) => {
|
|||||||
let newToken = randomStringBase62(64)
|
let newToken = randomStringBase62(64)
|
||||||
let newExpiration = Date.now() + 86400
|
let newExpiration = Date.now() + 86400
|
||||||
let newComment = `Login token for ${getHumanReadableUserAgent(rreq.get("User-Agent"))} on ${rreq.get("cf-connecting-ip") ?? rreq.ip}`
|
let newComment = `Login token for ${getHumanReadableUserAgent(rreq.get("User-Agent"))} on ${rreq.get("cf-connecting-ip") ?? rreq.ip}`
|
||||||
db`select * from users where oidc_username = ${fetchRes2.username};`.then(dbRes1 => {
|
|
||||||
db`insert into sessions (token,owner,scopes,expires,comment) values (${newToken},${dbRes1[0]?.id},${fetchRes2.enstrayedapi_scopes},${newExpiration},${newComment})`.then(dbRes2 => {
|
db`insert into sessions (token,owner,scopes,expires,comment) values (${newToken},(select id from users where oidc_username = ${fetchRes2.username}),${fetchRes2.enstrayedapi_scopes},${newExpiration},${newComment});`.then(dbRes1 => {
|
||||||
rres.send(dbRes2)
|
if (rreq.query.state.split("_")[0] === "redirect") {
|
||||||
})
|
let newDestination = atob(rreq.query.state.split("_")[1].replace("-","/"))
|
||||||
|
rres.setHeader("Set-Cookie", `APIToken=${newToken}; Domain=${rreq.hostname}; Expires=${new Date(newExpiration).toUTCString()}; Path=/`).redirect(newDestination)
|
||||||
|
} else if (rreq.query.state === "display") {
|
||||||
|
rres.setHeader("Set-Cookie", `APIToken=${newToken}; Domain=${rreq.hostname}; Expires=${new Date(newExpiration).toUTCString()}; Path=/`).send(`Success! Your token is <code>${newToken}</code>`)
|
||||||
|
} else if (rreq.query.state === "close") {
|
||||||
|
rres.setHeader("Set-Cookie", `APIToken=${newToken}; Domain=${rreq.hostname}; Expires=${new Date(newExpiration).toUTCString()}; Path=/`).send(`<script>document.addEventListener("DOMContentLoaded", () => {window.close();});</script> Success! You may now close this window.`)
|
||||||
|
} else {
|
||||||
|
rres.setHeader("Set-Cookie", `APIToken=${newToken}; Domain=${rreq.hostname}; Expires=${new Date(newExpiration).toUTCString()}; Path=/`).send(`Success! No state was provided, so you can close this window.`)
|
||||||
|
}
|
||||||
|
}).catch(dbErr => {
|
||||||
|
localError500(`Callback-Write-${dbErr}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}).catch(fetchErr2 => { // Fetch to userinfo endpoint failed for some other reason
|
}).catch(fetchErr2 => { // Fetch to userinfo endpoint failed for some other reason
|
||||||
|
|||||||
Reference in New Issue
Block a user