138 lines
3.7 KiB
JavaScript
138 lines
3.7 KiB
JavaScript
import { Router } from "express";
|
|
export const router = Router({ mergeParams: true }); ;
|
|
|
|
const checkAuth = global.utils.checkAuth;
|
|
|
|
/**
|
|
* GET - check authentication
|
|
* responses:
|
|
* - 200: {auth: true}
|
|
* - 401: {auth: false}
|
|
*/
|
|
router.get("/", async (req, res) => {
|
|
const auth = await checkAuth(req.cookies, res);
|
|
if (!auth) {
|
|
return;
|
|
}
|
|
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 repeat backends should not be requested
|
|
continue;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
exportCookies () {
|
|
return this.#cookies;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POST - safer ticket generation using proxmox authentication but adding HttpOnly
|
|
* request:
|
|
* - username: string
|
|
* - password: string
|
|
* responses:
|
|
* - 200: {auth: true}
|
|
* - 401: {auth: false}
|
|
*/
|
|
router.post("/ticket", async (req, res) => {
|
|
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 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 });
|
|
});
|
|
|
|
/**
|
|
* DELETE - request to destroy ticket
|
|
* responses:
|
|
* - 200: {auth: false}
|
|
*/
|
|
router.delete("/ticket", async (req, res) => {
|
|
if (Object.keys(req.cookies).length === 0) {
|
|
res.status(200).send({ auth: false });
|
|
return;
|
|
}
|
|
const domain = global.config.application.domain;
|
|
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 });
|
|
});
|
|
|
|
/**
|
|
* POST - change user password
|
|
* request:
|
|
* - password: string
|
|
* responses:
|
|
* - PAAS-LDAP API response
|
|
*/
|
|
router.post("/password", async (req, res) => {
|
|
const params = {
|
|
username: req.cookies.username,
|
|
password: req.body.password
|
|
};
|
|
|
|
const userRealm = params.username.split("@").at(-1);
|
|
const authHandlers = global.config.handlers.auth;
|
|
const userID = params.username.replace(`@${userRealm}`, "");
|
|
const userObj = { id: userID, realm: userRealm };
|
|
if (userRealm in authHandlers) {
|
|
const handler = authHandlers[userRealm];
|
|
const newAttributes = {
|
|
userpassword: params.password
|
|
};
|
|
const response = await handler.setUser(userObj, newAttributes, req.cookies);
|
|
if (response.ok) {
|
|
res.status(response.status).send(response.data);
|
|
}
|
|
else {
|
|
res.status(response.status).send({ error: response.data.error });
|
|
}
|
|
}
|
|
else {
|
|
res.status(501).send({ error: `Auth type ${userRealm} not implemented yet.` });
|
|
}
|
|
});
|