-
Notifications
You must be signed in to change notification settings - Fork 1
feat: 2fa backup codes #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: enhance-two-factor-security-foundation
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import React from "react"; | ||
| import { useFormContext } from "react-hook-form"; | ||
|
|
||
| import { useLocale } from "@calcom/lib/hooks/useLocale"; | ||
| import { Label, TextField } from "@calcom/ui"; | ||
|
|
||
| export default function TwoFactor({ center = true }) { | ||
| const { t } = useLocale(); | ||
| const methods = useFormContext(); | ||
|
|
||
| return ( | ||
| <div className={center ? "mx-auto !mt-0 max-w-sm" : "!mt-0 max-w-sm"}> | ||
| <Label className="mt-4">{t("backup_code")}</Label> | ||
|
|
||
| <p className="text-subtle mb-4 text-sm">{t("backup_code_instructions")}</p> | ||
|
|
||
| <TextField | ||
| id="backup-code" | ||
| label="" | ||
| defaultValue="" | ||
| placeholder="XXXXX-XXXXX" | ||
| minLength={10} // without dash | ||
| maxLength={11} // with dash | ||
| required | ||
| {...methods.register("backupCode")} | ||
| /> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,8 +43,30 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) | |
| return res.status(400).json({ error: ErrorCode.IncorrectPassword }); | ||
| } | ||
| } | ||
| // if user has 2fa | ||
| if (user.twoFactorEnabled) { | ||
|
|
||
| // if user has 2fa and using backup code | ||
| if (user.twoFactorEnabled && req.body.backupCode) { | ||
| if (!process.env.CALENDSO_ENCRYPTION_KEY) { | ||
| console.error("Missing encryption key; cannot proceed with backup code login."); | ||
| throw new Error(ErrorCode.InternalServerError); | ||
| } | ||
|
|
||
| if (!user.backupCodes) { | ||
| return res.status(400).json({ error: ErrorCode.MissingBackupCodes }); | ||
| } | ||
|
|
||
| const backupCodes = JSON.parse(symmetricDecrypt(user.backupCodes, process.env.CALENDSO_ENCRYPTION_KEY)); | ||
|
|
||
| // check if user-supplied code matches one | ||
| const index = backupCodes.indexOf(req.body.backupCode.replaceAll("-", "")); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Case-Sensitive Backup Code ValidationBackup code validation is case-sensitive due to the use of Locations (2) |
||
| if (index === -1) { | ||
| return res.status(400).json({ error: ErrorCode.IncorrectBackupCode }); | ||
| } | ||
|
|
||
| // we delete all stored backup codes at the end, no need to do this here | ||
|
|
||
| // if user has 2fa and NOT using backup code, try totp | ||
| } else if (user.twoFactorEnabled) { | ||
| if (!req.body.code) { | ||
| return res.status(400).json({ error: ErrorCode.SecondFactorRequired }); | ||
| // throw new Error(ErrorCode.SecondFactorRequired); | ||
|
|
@@ -82,6 +104,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) | |
| id: session.user.id, | ||
| }, | ||
| data: { | ||
| backupCodes: null, | ||
| twoFactorEnabled: false, | ||
| twoFactorSecret: null, | ||
| }, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Incorrect Default Function Name
The default exported function in
apps/web/components/auth/BackupCode.tsxis incorrectly namedTwoFactor. It should beBackupCodeto match the file name and the component's purpose of handling backup codes. This copy-paste error causes confusion and inconsistency.Locations (1)
apps/web/components/auth/BackupCode.tsx#L6-L7