diff --git a/src/app.ts b/src/app.ts index 8f1e4f3ce..171ac9222 100644 --- a/src/app.ts +++ b/src/app.ts @@ -7,7 +7,6 @@ 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"; @@ -15,8 +14,7 @@ import custom from "./routes/custom.js"; import error_handlers from "./routes/error_handlers.js"; import { startScheduledCleanup } from "./services/erase.js"; import sql_init from "./services/sql_init.js"; -import totp from "./services/totp.js"; -import oidc from "express-openid-connect"; +import { auth } from "express-openid-connect"; import openID from "./services/open_id.js"; import { t } from "i18next"; @@ -27,7 +25,6 @@ const app = express(); const scriptDir = dirname(fileURLToPath(import.meta.url)); - // Initialize DB sql_init.initializeDb(); @@ -62,14 +59,10 @@ 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 -totp.isTotpEnabled(); - if (openID.checkOpenIDRequirements()) - app.use(oidc.auth(openID.generateOAuthConfig())); + app.use(auth(openID.generateOAuthConfig())); await assets.register(app); routes.register(app); diff --git a/src/routes/auth_check.ts b/src/routes/auth_check.ts deleted file mode 100644 index 22418750b..000000000 --- a/src/routes/auth_check.ts +++ /dev/null @@ -1,29 +0,0 @@ -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/login.ts b/src/routes/login.ts index f3636422f..311637e02 100644 --- a/src/routes/login.ts +++ b/src/routes/login.ts @@ -21,6 +21,7 @@ function loginPage(req: Request, res: Response) { wrongPassword: false, wrongTotp: false, totpEnabled: totp.isTotpEnabled(), + ssoEnabled: open_id.isOpenIDEnabled(), assetPath: assetPath, appPath: appPath, }); @@ -70,13 +71,11 @@ function login(req: Request, res: Response) { const submittedPassword = req.body.password; const submittedTotpToken = req.body.totpToken; - // 首先验证密码 if (!verifyPassword(submittedPassword)) { sendLoginError(req, res, 'password'); return; } - // 如果密码正确且启用了 TOTP,验证 TOTP if (totp.isTotpEnabled()) { if (!verifyTOTP(submittedTotpToken)) { sendLoginError(req, res, 'totp'); @@ -95,7 +94,6 @@ function login(req: Request, res: Response) { req.session.cookie.maxAge = undefined; } - // 记录当前的认证状态 req.session.lastAuthState = { totpEnabled: totp.isTotpEnabled(), ssoEnabled: open_id.isOpenIDEnabled() @@ -134,6 +132,7 @@ function sendLoginError(req: Request, res: Response, errorType: 'password' | 'to wrongPassword: errorType === 'password', wrongTotp: errorType === 'totp', totpEnabled: totp.isTotpEnabled(), + ssoEnabled: open_id.isOpenIDEnabled(), assetPath: assetPath, appPath: appPath, }); diff --git a/src/services/auth.ts b/src/services/auth.ts index f2da22ed5..73a5a2ea0 100644 --- a/src/services/auth.ts +++ b/src/services/auth.ts @@ -1,5 +1,3 @@ -"use strict"; - import etapiTokenService from "./etapi_tokens.js"; import log from "./log.js"; import sqlInit from "./sql_init.js"; @@ -7,7 +5,8 @@ import { isElectron } from "./utils.js"; import passwordEncryptionService from "./encryption/password_encryption.js"; import config from "./config.js"; import passwordService from "./encryption/password.js"; -import openID from './open_id.js'; +import totp from "./totp.js"; +import open_id from "./open_id.js"; import open_id_encryption from './encryption/open_id_encryption.js'; import options from "./options.js"; import attributes from "./attributes.js"; @@ -16,9 +15,19 @@ import type { NextFunction, Request, Response } from "express"; const noAuthentication = config.General && config.General.noAuthentication === true; function checkAuth(req: Request, res: Response, next: NextFunction) { + const currentTotpStatus = totp.isTotpEnabled(); + const currentSsoStatus = open_id.isOpenIDEnabled(); + const lastAuthState = req.session.lastAuthState || { totpEnabled: false, ssoEnabled: false }; + if (!sqlInit.isDbInitialized()) { res.redirect('setup'); - } else if (openID.checkOpenIDRequirements()) { + } else if (currentTotpStatus !== lastAuthState.totpEnabled || currentSsoStatus !== lastAuthState.ssoEnabled) { + req.session.destroy((err) => { + if (err) console.error('Error destroying session:', err); + res.redirect('/login'); + }); + return; + } else if (open_id.isOpenIDEnabled()) { if ( req.oidc.isAuthenticated() && open_id_encryption.verifyOpenIDSubjectIdentifier(req.oidc.user?.sub)