Skip to content

Commit 6004f35

Browse files
committed
feat: enforce TOTP verification in checkCredentials middleware
1 parent aac5127 commit 6004f35

1 file changed

Lines changed: 30 additions & 10 deletions

File tree

apps/server/src/services/auth.ts

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
import etapiTokenService from "./etapi_tokens.js";
2-
import log from "./log.js";
3-
import sqlInit from "./sql_init.js";
4-
import { isElectron } from "./utils.js";
5-
import passwordEncryptionService from "./encryption/password_encryption.js";
1+
import type { NextFunction, Request, Response } from "express";
2+
3+
import attributes from "./attributes.js";
64
import config from "./config.js";
75
import passwordService from "./encryption/password.js";
8-
import totp from "./totp.js";
6+
import passwordEncryptionService from "./encryption/password_encryption.js";
7+
import recoveryCodeService from "./encryption/recovery_codes.js";
8+
import etapiTokenService from "./etapi_tokens.js";
9+
import log from "./log.js";
910
import openID from "./open_id.js";
1011
import options from "./options.js";
11-
import attributes from "./attributes.js";
12-
import type { NextFunction, Request, Response } from "express";
12+
import sqlInit from "./sql_init.js";
13+
import totp from "./totp.js";
14+
import { isElectron } from "./utils.js";
1315

1416
let noAuthentication = false;
1517
refreshAuth();
@@ -161,9 +163,27 @@ function checkCredentials(req: Request, res: Response, next: NextFunction) {
161163
if (!passwordEncryptionService.verifyPassword(password)) {
162164
res.setHeader("Content-Type", "text/plain").status(401).send("Incorrect password");
163165
log.info(`WARNING: Wrong password from ${req.ip}, rejecting.`);
164-
} else {
165-
next();
166+
return;
167+
}
168+
169+
// Verify TOTP if enabled
170+
if (totp.isTotpEnabled()) {
171+
const totpToken = req.headers["trilium-totp"] || "";
172+
if (typeof totpToken !== "string" || !totpToken) {
173+
res.setHeader("Content-Type", "text/plain").status(401).send("TOTP token is required");
174+
log.info(`WARNING: Missing TOTP token from ${req.ip}, rejecting.`);
175+
return;
176+
}
177+
178+
// Accept TOTP code or recovery code
179+
if (!totp.validateTOTP(totpToken) && !recoveryCodeService.verifyRecoveryCode(totpToken)) {
180+
res.setHeader("Content-Type", "text/plain").status(401).send("Incorrect TOTP token");
181+
log.info(`WARNING: Wrong TOTP token from ${req.ip}, rejecting.`);
182+
return;
183+
}
166184
}
185+
186+
next();
167187
}
168188

169189
export default {

0 commit comments

Comments
 (0)