allow backup code input for totp
This commit is contained in:
parent
11cbafb92a
commit
4b34353354
4 changed files with 10 additions and 5 deletions
|
@ -11,7 +11,9 @@ export async function verifyTotpCode(
|
||||||
secret: string,
|
secret: string,
|
||||||
userId: string
|
userId: string
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
if (code.length !== 6) {
|
// if code is digits only, it's totp
|
||||||
|
const isTotp = /^\d+$/.test(code);
|
||||||
|
if (!isTotp) {
|
||||||
const validBackupCode = await verifyBackUpCode(code, userId);
|
const validBackupCode = await verifyBackUpCode(code, userId);
|
||||||
return validBackupCode;
|
return validBackupCode;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -118,7 +118,7 @@ export async function verifyTotp(
|
||||||
async function generateBackupCodes(): Promise<string[]> {
|
async function generateBackupCodes(): Promise<string[]> {
|
||||||
const codes = [];
|
const codes = [];
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
const code = generateRandomString(8, alphabet("0-9", "A-Z", "a-z"));
|
const code = generateRandomString(6, alphabet("0-9", "A-Z", "a-z"));
|
||||||
codes.push(code);
|
codes.push(code);
|
||||||
}
|
}
|
||||||
return codes;
|
return codes;
|
||||||
|
|
|
@ -45,6 +45,7 @@ import { createApiClient } from "@app/api";
|
||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
import { passwordSchema } from "@server/auth/passwordSchema";
|
import { passwordSchema } from "@server/auth/passwordSchema";
|
||||||
import { get } from "http";
|
import { get } from "http";
|
||||||
|
import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp";
|
||||||
|
|
||||||
const requestSchema = z.object({
|
const requestSchema = z.object({
|
||||||
email: z.string().email()
|
email: z.string().email()
|
||||||
|
@ -354,6 +355,7 @@ export default function ResetPasswordForm({
|
||||||
<InputOTP
|
<InputOTP
|
||||||
maxLength={6}
|
maxLength={6}
|
||||||
{...field}
|
{...field}
|
||||||
|
pattern={REGEXP_ONLY_DIGITS_AND_CHARS}
|
||||||
>
|
>
|
||||||
<InputOTPGroup>
|
<InputOTPGroup>
|
||||||
<InputOTPSlot
|
<InputOTPSlot
|
||||||
|
|
|
@ -36,6 +36,7 @@ import {
|
||||||
InputOTPSlot
|
InputOTPSlot
|
||||||
} from "./ui/input-otp";
|
} from "./ui/input-otp";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp";
|
||||||
|
|
||||||
type LoginFormProps = {
|
type LoginFormProps = {
|
||||||
redirect?: string;
|
redirect?: string;
|
||||||
|
@ -61,7 +62,7 @@ export default function LoginForm({ redirect, onLogin }: LoginFormProps) {
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const [mfaRequested, setMfaRequested] = useState(false);
|
const [mfaRequested, setMfaRequested] = useState(true);
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof formSchema>>({
|
const form = useForm<z.infer<typeof formSchema>>({
|
||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
|
@ -129,7 +130,7 @@ export default function LoginForm({ redirect, onLogin }: LoginFormProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="space-y-8">
|
||||||
{!mfaRequested && (
|
{!mfaRequested && (
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form
|
<form
|
||||||
|
@ -213,7 +214,7 @@ export default function LoginForm({ redirect, onLogin }: LoginFormProps) {
|
||||||
<FormLabel>Authenticator Code</FormLabel>
|
<FormLabel>Authenticator Code</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
<InputOTP maxLength={6} {...field}>
|
<InputOTP maxLength={6} {...field} pattern={REGEXP_ONLY_DIGITS_AND_CHARS}>
|
||||||
<InputOTPGroup>
|
<InputOTPGroup>
|
||||||
<InputOTPSlot index={0} />
|
<InputOTPSlot index={0} />
|
||||||
<InputOTPSlot index={1} />
|
<InputOTPSlot index={1} />
|
||||||
|
|
Loading…
Add table
Reference in a new issue