Skip to content

feat: 2fa backup codes#1

Open
ShashankFC wants to merge 1 commit into
enhance-two-factor-security-foundationfrom
improve-two-factor-authentication-features
Open

feat: 2fa backup codes#1
ShashankFC wants to merge 1 commit into
enhance-two-factor-security-foundationfrom
improve-two-factor-authentication-features

Conversation

@ShashankFC

@ShashankFC ShashankFC commented Jan 22, 2026

Copy link
Copy Markdown

Test 3

Summary by CodeRabbit

Release Notes

  • New Features
    • Added backup codes as a secondary two-factor authentication method
    • Users can download, copy, and view backup codes when enabling 2FA
    • Added "Lost Access" recovery option allowing users to authenticate with backup codes if their authenticator app is unavailable
    • Users can disable 2FA using backup codes if they've lost access to their primary method

✏️ Tip: You can customize this high-level summary in your review settings.


Replicated from ai-code-review-evaluation/cal.com-coderabbit#3


Note

High Risk
Touches authentication and 2FA disable logic and introduces new encrypted secrets persisted to the user table, so mistakes could cause account lockouts or weaken recovery security.

Overview
Adds 2FA backup codes as an alternate second factor: the setup API now generates and returns 10 random codes, stores them encrypted in the new users.backupCodes column, and the enable modal displays them with copy/download/close actions.

Updates authentication and settings flows to accept a backupCode in addition to TOTP: credential auth can validate and consume a backup code for login, the disable-2FA endpoint can validate a backup code and clears backupCodes when turning 2FA off, and the UI adds a “Lost access” toggle on login/disable modals (plus minor input autofocus/tabIndex tweaks).

Written by Cursor Bugbot for commit a308075. Configure here.

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
@ShashankFC

Copy link
Copy Markdown
Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

);

// check if user-supplied code matches one
const index = backupCodes.indexOf(credentials.backupCode.replaceAll("-", ""));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case-sensitive backup code comparison rejects valid uppercase input

Medium Severity

Backup codes are generated as lowercase hex via crypto.randomBytes(5).toString("hex"), but the comparison in both the login and disable endpoints uses indexOf without case normalization — only dashes are stripped with replaceAll("-", ""). A user who manually types their backup code with uppercase hex letters (A–F) will get a rejection even though the code is valid. This is especially problematic in the "lost access" recovery flow, where the user may already be locked out.

Additional Locations (1)

Fix in Cursor Fix in Web

import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Label, TextField } from "@calcom/ui";

export default function TwoFactor({ center = true }) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BackupCode component function misleadingly named TwoFactor

Low Severity

The BackupCode.tsx file exports function TwoFactor, which is the same function name used by the actual TwoFactor component in TwoFactor.tsx. Since both are default exports, imports work fine, but React DevTools and error stack traces will show both components identically as "TwoFactor", making debugging confusing. The function name here would logically be BackupCode.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants