diff --git a/src/app.ts b/src/app.ts index 4799ac3fd..8f1e4f3ce 100644 --- a/src/app.ts +++ b/src/app.ts @@ -7,6 +7,7 @@ import compression from "compression"; import { fileURLToPath } from "url"; import { dirname } from "path"; import sessionParser from "./routes/session_parser.js"; +import checkAuthState from "./routes/auth_check.js"; import utils from "./services/utils.js"; import assets from "./routes/assets.js"; import routes from "./routes/routes.js"; @@ -61,6 +62,7 @@ app.use(`/manifest.webmanifest`, express.static(path.join(scriptDir, "public/man app.use(`/robots.txt`, express.static(path.join(scriptDir, "public/robots.txt"))); app.use(`/icon.png`, express.static(path.join(scriptDir, "public/icon.png"))); app.use(sessionParser); +app.use(checkAuthState); app.use(favicon(`${scriptDir}/../images/app-icons/icon.ico`)); // Check if TOTP is enabled and validate TOTP secret is set diff --git a/src/routes/auth_check.ts b/src/routes/auth_check.ts new file mode 100644 index 000000000..22418750b --- /dev/null +++ b/src/routes/auth_check.ts @@ -0,0 +1,29 @@ +import totp from "../services/totp.js"; +import open_id from "../services/open_id.js"; +import type { Request, Response, NextFunction } from "express"; + + +export default function checkAuthState(req: Request, res: Response, next: NextFunction) { + if (!req.session.loggedIn || req.path === '/login') return next(); + + const currentTotpStatus = totp.isTotpEnabled(); + const currentSsoStatus = open_id.isOpenIDEnabled(); + const lastAuthState = req.session.lastAuthState || { totpEnabled: false, ssoEnabled: false }; + + if (lastAuthState.totpEnabled !== currentTotpStatus || + lastAuthState.ssoEnabled !== currentSsoStatus) { + req.session.destroy((err) => { + if (err) console.error('Error destroying session:', err); + + if (typeof res.redirect === 'function') { + res.redirect('/login'); + } else { + console.warn("res.redirect unavailable"); + res.end?.(); + } + }); + return; + } + + next(); +} diff --git a/src/routes/session_parser.ts b/src/routes/session_parser.ts index d8e1add6c..cc69cc6a2 100644 --- a/src/routes/session_parser.ts +++ b/src/routes/session_parser.ts @@ -3,9 +3,6 @@ import sessionFileStore from "session-file-store"; import sessionSecret from "../services/session_secret.js"; import dataDir from "../services/data_dir.js"; import config from "../services/config.js"; -import totp from "../services/totp.js"; -import open_id from "../services/open_id.js"; -import type { Request, Response, NextFunction } from "express"; const FileStore = sessionFileStore(session); @@ -25,35 +22,4 @@ const sessionParser = session({ }) }); -const checkAuthState = (req: Request, res: Response, next: NextFunction) => { - if (!req.session.loggedIn || req.path === '/login') { - return next(); - } - - const currentTotpStatus = totp.isTotpEnabled(); - const currentSsoStatus = open_id.isOpenIDEnabled(); - - const lastAuthState = req.session.lastAuthState || { - totpEnabled: false, - ssoEnabled: false - }; - - if (lastAuthState.totpEnabled !== currentTotpStatus || - lastAuthState.ssoEnabled !== currentSsoStatus) { - req.session.destroy((err) => { - if (err) { - console.error('Error destroying session:', err); - } - res.redirect('/login'); - }); - return; - } - - next(); -}; - -export default function (req: Request, res: Response, next: NextFunction) { - sessionParser(req, res, () => { - checkAuthState(req, res, next); - }); -} +export default sessionParser;