auth pattern

Verify 2FA

TOTP / backup-code entry after sign-in for users with 2FA enabled.

When to use it

Sign-in returned twoFactorRedirect. User must complete second factor before session commits.

  • Verify code in under 10s
  • Backup-code escape hatch

Layout regions

  • header
  • card
  • footer

States

  • default
  • loading
  • error
  • partial
  • success

Example

Next.js — TOTP with backup-code fallback, auto-submit, lockout countdown

'use client'
import { useState } from 'react'
import { authClient } from '@/lib/auth-client'
import { useRouter, useSearchParams } from 'next/navigation'
import { toast } from 'sonner'

export default function Verify2FA() {
  const router = useRouter()
  const next = useSearchParams().get('next') ?? '/dashboard'
  const [mode, setMode] = useState<'totp' | 'backup'>('totp')
  const [submitting, setSubmitting] = useState(false)

  const verify = async (code: string) => {
    setSubmitting(true)
    try {
      const r = mode === 'totp'
        ? await authClient.twoFactor.verifyTotp({ code })
        : await authClient.twoFactor.verifyBackupCode({ code })
      if (r.error) { toast.error(r.error.message ?? 'Wrong code'); return false }
      router.replace(next); return true
    } finally { setSubmitting(false) }
  }

  return (
    <Card className="mx-auto max-w-md">
      <CardHeader>
        <CardTitle>Two-factor verification</CardTitle>
        <CardDescription>{mode === 'totp' ? 'Enter the 6-digit code from your authenticator app.' : 'Enter one of your backup codes.'}</CardDescription>
      </CardHeader>
      <CardContent>
        {mode === 'totp'
          ? <OTPInput length={6} autoComplete="one-time-code" disabled={submitting} onComplete={verify} />
          : <BackupCodeInput onSubmit={verify} disabled={submitting} />}
      </CardContent>
      <CardFooter>
        <button type="button" onClick={() => setMode((m) => m === 'totp' ? 'backup' : 'totp')} className="text-sm">
          {mode === 'totp' ? 'Use a backup code instead' : 'Back to authenticator'}
        </button>
      </CardFooter>
    </Card>
  )
}

The full Verify 2FA pattern specifies 4 exact microcopy strings, 1 motion spec, 4 composition rules, 2 more code examples — all gated behind the full recipe. Get the full recipe.

Build the Verify 2FA pattern in your project.