[GH-ISSUE #750] Error verifying the backup code #8410

Closed
opened 2026-04-13 03:28:44 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @MarcosHelbert on GitHub (Dec 3, 2024).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/750

Describe the bug
There is an error that occurs while verifying a backup code. The error message appears as "TypeError Cannot read properties of undefined (reading 'token')". The application is using Prisma with PostgreSQL database.

To Reproduce

"use client";

import { Dispatch, SetStateAction, useEffect, useTransition } from "react";
import { BackupCodeSchema } from "@/schemas/auth/backup-code-schema";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";

import { authClient } from "@/lib/auth/client";
import { useIsClient } from "@/hooks/use-is-client";
import { toast } from "@/hooks/use-toast";
import {
    Form,
    FormControl,
    FormField,
    FormItem,
    FormLabel,
    FormMessage,
} from "@/components/ui/shadcn/form";
import { Input } from "@/components/ui/shadcn/input";

import { AuthButton } from "../form-components/auth-button";

type BackupCodeFormProps = {
    setPending: Dispatch<SetStateAction<boolean>>;
};

export function BackupCodeForm({ setPending }: BackupCodeFormProps) {
    const isClient = useIsClient();
    const [isPending, startTransition] = useTransition();

    useEffect(() => {
        setPending(isPending);
    }, [isPending]);

    const form = useForm<z.infer<typeof BackupCodeSchema>>({
        resolver: zodResolver(BackupCodeSchema),
        defaultValues: {
            backupCode: "",
        },
    });

    const onSubmit = form.handleSubmit((data: z.infer<typeof BackupCodeSchema>) => {
        startTransition(async () => {
            try {
                await authClient.twoFactor.verifyBackupCode({
                    code: data.backupCode,
                    fetchOptions: {
                        onError(ctx) {
                            if (ctx.error.code === "INVALID_BACKUP_CODE") {
                                form.setError("backupCode", {
                                    message: "Invalid backup code",
                                });
                                return;
                            }

                            if (ctx.error.code === "INVALID_TWO_FACTOR_COOKIE") {
                                toast({
                                    title: "Invalid Two-Factor Token",
                                    description: "Your session has expired. Please log in again.",
                                });
                                return;
                            }

                            throw new Error(ctx.error?.message);
                        },
                        onSuccess(ctx) {
                            console.log(ctx);
                        },
                    },
                });
            } catch (error) {
                toast({
                    title: "Backup Code Error",
                    description:
                        "There was an issue with the backup code. Please check and try again.",
                });
            }
        });
    });

    return (
        <Form {...form}>
            <form className="grid w-full gap-2" onSubmit={onSubmit}>
                <FormField
                    control={form.control}
                    name="backupCode"
                    render={({ field }) => (
                        <FormItem className="flex flex-col items-center gap-3 space-y-0 pt-1.5">
                            <FormLabel htmlFor="backupCode" className="text-center">
                                backup code
                            </FormLabel>
                            <FormControl>
                                <Input
                                    id="backupCode"
                                    type="text"
                                    disabled={isPending}
                                    placeholder="XXXXX-XXXXX"
                                    className="text-center"
                                    {...field}
                                    pattern="[a-z0-9]{5}-[a-z0-9]{5}"
                                />
                            </FormControl>
                            <FormMessage />
                        </FormItem>
                    )}
                />
                <AuthButton isPending={isPending}>Verify Code</AuthButton>
            </form>
        </Form>
    );
}

Expected behavior
When a user submits a valid backup code, it should execute what's inside success and redirect.

Screenshots
image

Originally created by @MarcosHelbert on GitHub (Dec 3, 2024). Original GitHub issue: https://github.com/better-auth/better-auth/issues/750 **Describe the bug** There is an error that occurs while verifying a backup code. The error message appears as "TypeError Cannot read properties of undefined (reading 'token')". The application is using Prisma with PostgreSQL database. **To Reproduce** ```tsx "use client"; import { Dispatch, SetStateAction, useEffect, useTransition } from "react"; import { BackupCodeSchema } from "@/schemas/auth/backup-code-schema"; import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { authClient } from "@/lib/auth/client"; import { useIsClient } from "@/hooks/use-is-client"; import { toast } from "@/hooks/use-toast"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/shadcn/form"; import { Input } from "@/components/ui/shadcn/input"; import { AuthButton } from "../form-components/auth-button"; type BackupCodeFormProps = { setPending: Dispatch<SetStateAction<boolean>>; }; export function BackupCodeForm({ setPending }: BackupCodeFormProps) { const isClient = useIsClient(); const [isPending, startTransition] = useTransition(); useEffect(() => { setPending(isPending); }, [isPending]); const form = useForm<z.infer<typeof BackupCodeSchema>>({ resolver: zodResolver(BackupCodeSchema), defaultValues: { backupCode: "", }, }); const onSubmit = form.handleSubmit((data: z.infer<typeof BackupCodeSchema>) => { startTransition(async () => { try { await authClient.twoFactor.verifyBackupCode({ code: data.backupCode, fetchOptions: { onError(ctx) { if (ctx.error.code === "INVALID_BACKUP_CODE") { form.setError("backupCode", { message: "Invalid backup code", }); return; } if (ctx.error.code === "INVALID_TWO_FACTOR_COOKIE") { toast({ title: "Invalid Two-Factor Token", description: "Your session has expired. Please log in again.", }); return; } throw new Error(ctx.error?.message); }, onSuccess(ctx) { console.log(ctx); }, }, }); } catch (error) { toast({ title: "Backup Code Error", description: "There was an issue with the backup code. Please check and try again.", }); } }); }); return ( <Form {...form}> <form className="grid w-full gap-2" onSubmit={onSubmit}> <FormField control={form.control} name="backupCode" render={({ field }) => ( <FormItem className="flex flex-col items-center gap-3 space-y-0 pt-1.5"> <FormLabel htmlFor="backupCode" className="text-center"> backup code </FormLabel> <FormControl> <Input id="backupCode" type="text" disabled={isPending} placeholder="XXXXX-XXXXX" className="text-center" {...field} pattern="[a-z0-9]{5}-[a-z0-9]{5}" /> </FormControl> <FormMessage /> </FormItem> )} /> <AuthButton isPending={isPending}>Verify Code</AuthButton> </form> </Form> ); } ``` **Expected behavior** When a user submits a valid backup code, it should execute what's inside success and redirect. **Screenshots** ![image](https://github.com/user-attachments/assets/0035a13f-a669-40f4-bcc8-d74800b7bb68)
GiteaMirror added the locked label 2026-04-13 03:28:44 -05:00
Author
Owner

@Bekacru commented on GitHub (Dec 3, 2024):

which version of better auth are you on?

<!-- gh-comment-id:2515148536 --> @Bekacru commented on GitHub (Dec 3, 2024): which version of better auth are you on?
Author
Owner

@MarcosHelbert commented on GitHub (Dec 3, 2024):

v1.0.9

<!-- gh-comment-id:2515154154 --> @MarcosHelbert commented on GitHub (Dec 3, 2024): v1.0.9
Author
Owner

@Bekacru commented on GitHub (Dec 3, 2024):

should be fixed on 1.0.10-beta.2

<!-- gh-comment-id:2515217212 --> @Bekacru commented on GitHub (Dec 3, 2024): should be fixed on `1.0.10-beta.2`
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#8410