Skip to content

Commit

Permalink
fixed issue with backup codes not working
Browse files Browse the repository at this point in the history
  • Loading branch information
rubentalstra committed Feb 6, 2025
1 parent 9773aa8 commit 9fb122c
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 16 deletions.
8 changes: 4 additions & 4 deletions api/server/controllers/TwoFactorController.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ const enable2FAController = async (req, res) => {
try {
const userId = req.user.id;
const secret = generateTOTPSecret();
const { plainCodes, hashedCodes } = generateBackupCodes();
const { plainCodes, codeObjects } = generateBackupCodes();

const user = await User.findByIdAndUpdate(
userId,
{ totpSecret: secret, backupCodes: hashedCodes },
{ totpSecret: secret, backupCodes: codeObjects },
{ new: true },
);

Expand Down Expand Up @@ -84,10 +84,10 @@ const disable2FAController = async (req, res) => {
const regenerateBackupCodesController = async (req, res) => {
try {
const userId = req.user.id;
const { plainCodes, hashedCodes } = generateBackupCodes();
const { plainCodes, codeObjects } = generateBackupCodes();
await User.findByIdAndUpdate(
userId,
{ backupCodes: hashedCodes },
{ backupCodes: codeObjects },
{ new: true },
);
res.status(200).json({ message: 'Backup codes regenerated.', backupCodes: plainCodes });
Expand Down
20 changes: 8 additions & 12 deletions api/server/controllers/auth/TwoFactorAuthController.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const verify2FA = async (req, res) => {
if (!tempToken) {
return res.status(400).json({ message: 'Missing temporary token' });
}
// Verify the temporary token.
let payload;
try {
payload = jwt.verify(tempToken, process.env.JWT_2FA_SECRET);
Expand All @@ -27,31 +26,28 @@ const verify2FA = async (req, res) => {
if (token && verifyTOTP(user.totpSecret, token)) {
verified = true;
} else if (backupCode) {
// Hash the provided backup code.
const hashedInput = crypto.createHash('sha256').update(backupCode).digest('hex');

// Check if there is an unused backup code with the matching hash.
const matchingCode = user.backupCodes.find(codeObj =>
codeObj.codeHash === hashedInput && codeObj.used === false,
const backupCodeInput = backupCode.trim();
const hashedInput = crypto
.createHash('sha256')
.update(backupCodeInput)
.digest('hex');
const matchingCode = user.backupCodes.find(
(codeObj) => codeObj.codeHash === hashedInput && codeObj.used === false,
);

if (matchingCode) {
verified = true;
// Update the backup codes array by marking the matching code as used.
const updatedBackupCodes = user.backupCodes.map(codeObj => {
const updatedBackupCodes = user.backupCodes.map((codeObj) => {
if (codeObj.codeHash === hashedInput && codeObj.used === false) {
return { ...codeObj, used: true, usedAt: new Date() };
}
return codeObj;
});
// Use the updateUser helper to update the backupCodes field.
await updateUser(user._id, { backupCodes: updatedBackupCodes });
}
}
if (!verified) {
return res.status(401).json({ message: 'Invalid 2FA code or backup code' });
}
// 2FA passed: generate full auth tokens.
const { password: _, __v, ...userData } = user.toObject ? user.toObject() : user;
userData.id = user._id.toString();
const authToken = await setAuthTokens(user._id, res);
Expand Down

0 comments on commit 9fb122c

Please sign in to comment.