fix issues in backend implementions,
auth endpoint now fetches all relevant backend tokens
This commit is contained in:
@@ -17,6 +17,34 @@ router.get("/", async (req, res) => {
|
||||
res.status(200).send({ auth: true });
|
||||
});
|
||||
|
||||
/**
|
||||
* Fetches and consumes cookies from backends and avoids duplicate cookies from repeat backends. Also helps handle errors.
|
||||
*/
|
||||
class CookieFetcher {
|
||||
#fetchedBackends = [];
|
||||
#cookies = [];
|
||||
async fetchBackends (backends, credentials) {
|
||||
for (const backend of backends) {
|
||||
if (this.#fetchedBackends.indexOf(backend) === -1) {
|
||||
const response = await backend.openSession(credentials);
|
||||
if (!response.ok) {
|
||||
return false;
|
||||
}
|
||||
this.#cookies = this.#cookies.concat(response.cookies);
|
||||
this.#fetchedBackends.push(backend);
|
||||
}
|
||||
else { // assume that a repeat backends should not be requested
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
exportCookies () {
|
||||
return this.#cookies;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* POST - safer ticket generation using proxmox authentication but adding HttpOnly
|
||||
* request:
|
||||
@@ -27,22 +55,29 @@ router.get("/", async (req, res) => {
|
||||
* - 401: {auth: false}
|
||||
*/
|
||||
router.post("/ticket", async (req, res) => {
|
||||
const body = JSON.parse(JSON.stringify(req.body));
|
||||
const response = await global.pve.requestPVE("/access/ticket", "POST", null, body);
|
||||
if (!(response.status === 200)) {
|
||||
res.status(response.status).send({ auth: false });
|
||||
res.end();
|
||||
const params = {
|
||||
username: req.body.username,
|
||||
password: req.body.password
|
||||
};
|
||||
const domain = global.config.application.domain;
|
||||
const userRealm = params.username.split("@").at(-1);
|
||||
const backends = [global.pve, global.db];
|
||||
if (userRealm in global.auth) {
|
||||
backends.push(global.auth[userRealm]);
|
||||
}
|
||||
const cm = new CookieFetcher();
|
||||
const success = await cm.fetchBackends(backends, params);
|
||||
if (!success) {
|
||||
res.status(401).send({ auth: false });
|
||||
return;
|
||||
}
|
||||
const domain = global.config.application.domain;
|
||||
const ticket = response.data.data.ticket;
|
||||
const csrftoken = response.data.data.CSRFPreventionToken;
|
||||
const username = response.data.data.username;
|
||||
const expire = new Date(Date.now() + (2 * 60 * 60 * 1000));
|
||||
res.cookie("PVEAuthCookie", ticket, { domain, path: "/", httpOnly: true, secure: true, expires: expire });
|
||||
res.cookie("CSRFPreventionToken", csrftoken, { domain, path: "/", httpOnly: true, secure: true, expires: expire });
|
||||
res.cookie("username", username, { domain, path: "/", secure: true, expires: expire });
|
||||
res.cookie("auth", 1, { domain, path: "/", secure: true, expires: expire });
|
||||
const cookies = cm.exportCookies();
|
||||
for (const cookie of cookies) {
|
||||
const expiresDate = new Date(Date.now() + cookie.expiresMSFromNow);
|
||||
res.cookie(cookie.name, cookie.value, { domain, path: "/", httpOnly: true, secure: true, expires: expiresDate });
|
||||
}
|
||||
res.cookie("username", params.username, { domain, path: "/", secure: true });
|
||||
res.cookie("auth", 1, { domain, path: "/", secure: true });
|
||||
res.status(200).send({ auth: true });
|
||||
});
|
||||
|
||||
@@ -52,12 +87,17 @@ router.post("/ticket", async (req, res) => {
|
||||
* - 200: {auth: false}
|
||||
*/
|
||||
router.delete("/ticket", async (req, res) => {
|
||||
const expire = new Date(0);
|
||||
if (Object.keys(req.cookies).length === 0) {
|
||||
res.status(200).send({ auth: false });
|
||||
return;
|
||||
}
|
||||
const domain = global.config.application.domain;
|
||||
res.cookie("PVEAuthCookie", "", { domain, path: "/", httpOnly: true, secure: true, expires: expire });
|
||||
res.cookie("CSRFPreventionToken", "", { domain, path: "/", httpOnly: true, secure: true, expires: expire });
|
||||
res.cookie("username", "", { domain, path: "/", httpOnly: true, secure: true, expires: expire });
|
||||
res.cookie("auth", 0, { domain, path: "/", expires: expire });
|
||||
const expire = new Date(0);
|
||||
for (const cookie in req.cookies) {
|
||||
res.cookie(cookie, "", { domain, path: "/", expires: expire });
|
||||
}
|
||||
await global.pve.closeSession(req.cookies);
|
||||
await global.db.closeSession(req.cookies);
|
||||
res.status(200).send({ auth: false });
|
||||
});
|
||||
|
||||
@@ -80,13 +120,11 @@ router.post("/password", async (req, res) => {
|
||||
};
|
||||
|
||||
const userRealm = params.username.split("@").at(-1);
|
||||
const domains = (await global.pve.requestPVE("/access/domains", "GET", { token: true })).data.data;
|
||||
const realm = domains.find((e) => e.realm === userRealm);
|
||||
const authHandlers = global.config.handlers.auth;
|
||||
|
||||
if (realm.type in authHandlers) {
|
||||
const handler = authHandlers[realm.type];
|
||||
const userID = params.username.replace(`@${realm.realm}`, "");
|
||||
if (userRealm in authHandlers) {
|
||||
const handler = authHandlers[userRealm];
|
||||
const userID = params.username.replace(`@${userRealm}`, "");
|
||||
const newAttributes = {
|
||||
userpassword: params.password
|
||||
};
|
||||
@@ -103,6 +141,6 @@ router.post("/password", async (req, res) => {
|
||||
}
|
||||
}
|
||||
else {
|
||||
res.status(501).send({ error: `Auth type ${realm.type} not implemented yet.` });
|
||||
res.status(501).send({ error: `Auth type ${userRealm} not implemented yet.` });
|
||||
}
|
||||
});
|
||||
|
Reference in New Issue
Block a user