import { useState } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Loader2, Shield, AlertCircle } from 'lucide-react'; import { twoFactorService } from '@/services/2fa-service'; import { useToast } from '@/hooks/useToast'; import { parseApiError } from '@/utils/apiErrorHandler'; interface TwoFactorVerifyProps { onSuccess: (code: string) => void; onCancel: () => void; } export function TwoFactorVerify({ onSuccess, onCancel }: TwoFactorVerifyProps) { const [code, setCode] = useState(''); const [backupCode, setBackupCode] = useState(''); const [useBackupCode, setUseBackupCode] = useState(false); const [isVerifying, setIsVerifying] = useState(false); const [error, setError] = useState(''); const { toast } = useToast(); const handleVerify = async () => { if (!code && !backupCode) { setError('Please enter a verification code'); return; } try { setIsVerifying(true); setError(''); const verificationCode = useBackupCode ? backupCode : code; // TODO: Fix 2FA login verification // Issue: twoFactorService.verify(secret, code) is for 2FA setup, not login verification. // During login, we don't have the secret. The 2FA code should be verified as part of // the login flow (either via a separate endpoint like /auth/login/2fa or by including // the code in the login request when requires_2fa is true). // Current workaround: Pass code to parent via onSuccess() - parent should handle verification. // Action required: Check backend API contract for 2FA login verification endpoint. try { // FIXME: This is incorrect - verify() is for setup, not login // Remove this call once proper login 2FA verification is implemented await twoFactorService.verify('', verificationCode); onSuccess(verificationCode); } catch (verifyError: unknown) { // If verification fails, show error message const apiError = parseApiError(verifyError); const errorMessage = apiError.message; setError(errorMessage); toast({ message: errorMessage, type: 'error', }); throw verifyError; // Re-throw to be caught by outer catch if needed } } catch (error: unknown) { const apiError = parseApiError(error); setError(apiError.message); toast({ message: apiError.message, type: 'error', }); } finally { setIsVerifying(false); } }; return ( Two-Factor Authentication Enter the code from your authenticator app Enter the 6-digit code from your authenticator app to continue signing in. {error && ( {error} )} {!useBackupCode ? ( <>
{ setCode(e.target.value.replace(/\D/g, '').slice(0, 6)); setError(''); }} maxLength={6} className="text-center text-2xl tracking-widest" autoFocus />

Lost access?{' '}

) : ( <>
{ setBackupCode(e.target.value); setError(''); }} />

)}
); }