🔒 fix: 2FA Encrypt TOTP Secrets & Improve Docs (#5933)

* 🔒 fix: Integrate TOTP secret retrieval and encryption in Two-Factor Authentication

* 🔒 refactor: Simplify TOTP verification by removing commented-out code
This commit is contained in:
Ruben Talstra 2025-02-19 19:33:29 +01:00 committed by GitHub
parent 06282b584f
commit 538a2a144a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 84 additions and 41 deletions

View file

@ -3,9 +3,11 @@ const {
verifyBackupCode,
generateTOTPSecret,
generateBackupCodes,
getTOTPSecret,
} = require('~/server/services/twoFactorService');
const { updateUser, getUserById } = require('~/models');
const { logger } = require('~/config');
const { encryptV2 } = require('~/server/utils/crypto');
const enable2FAController = async (req, res) => {
const safeAppTitle = (process.env.APP_TITLE || 'LibreChat').replace(/\s+/g, '');
@ -15,7 +17,8 @@ const enable2FAController = async (req, res) => {
const secret = generateTOTPSecret();
const { plainCodes, codeObjects } = await generateBackupCodes();
const user = await updateUser(userId, { totpSecret: secret, backupCodes: codeObjects });
const encryptedSecret = await encryptV2(secret);
const user = await updateUser(userId, { totpSecret: encryptedSecret, backupCodes: codeObjects });
const otpauthUrl = `otpauth://totp/${safeAppTitle}:${user.email}?secret=${secret}&issuer=${safeAppTitle}`;
@ -38,14 +41,16 @@ const verify2FAController = async (req, res) => {
return res.status(400).json({ message: '2FA not initiated' });
}
let verified = false;
if (token && (await verifyTOTP(user.totpSecret, token))) {
// Retrieve the plain TOTP secret using getTOTPSecret.
const secret = await getTOTPSecret(user.totpSecret);
if (token && (await verifyTOTP(secret, token))) {
return res.status(200).json();
} else if (backupCode) {
verified = await verifyBackupCode({ user, backupCode });
}
if (verified) {
return res.status(200).json();
const verified = await verifyBackupCode({ user, backupCode });
if (verified) {
return res.status(200).json();
}
}
return res.status(400).json({ message: 'Invalid token.' });
@ -65,7 +70,10 @@ const confirm2FAController = async (req, res) => {
return res.status(400).json({ message: '2FA not initiated' });
}
if (await verifyTOTP(user.totpSecret, token)) {
// Retrieve the plain TOTP secret using getTOTPSecret.
const secret = await getTOTPSecret(user.totpSecret);
if (await verifyTOTP(secret, token)) {
return res.status(200).json();
}