import { useState } from 'react' import { Loader2, Lock, ShieldCheck } from 'lucide-react' import { authApi, type EnrollResult } from '../lib/auth' import { useAuth } from '../lib/useAuth' type Step = 'credentials' | 'verify' | 'enroll' // Login is the unauthenticated gate. Stage 1 is email and password (returns a pre MFA session cookie); // stage 2 is mandatory TOTP, either verifying an existing enrollment or enrolling for the first time. // On an active session it calls refresh, which flips the AuthProvider to show the app. export function Login() { const { refresh } = useAuth() const [step, setStep] = useState('credentials') const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [code, setCode] = useState('') const [useRecovery, setUseRecovery] = useState(false) const [enroll, setEnroll] = useState(null) const [err, setErr] = useState('') const [busy, setBusy] = useState(false) async function beginEnroll() { setBusy(true) try { setEnroll(await authApi.mfaEnroll()) setStep('enroll') } catch { setErr('Could not start MFA enrollment. Try again.') } finally { setBusy(false) } } async function onCredentials(e: React.FormEvent) { e.preventDefault() setErr('') setBusy(true) try { const r = await authApi.login(email, password) if (!r.mfa_required) { // MFA is disabled for this pilot: the session is already active, go straight in. await refresh() setBusy(false) return } setCode('') if (r.mfa_enrolled) { setStep('verify') setBusy(false) } else { await beginEnroll() } } catch { setErr('Invalid email or password.') setBusy(false) } } async function onVerify(e: React.FormEvent) { e.preventDefault() setErr('') setBusy(true) try { if (useRecovery) { await authApi.mfaRecover(code.trim()) } else { await authApi.mfaVerify(code.trim()) } await refresh() } catch { setErr(useRecovery ? 'Invalid recovery code.' : 'Invalid authentication code.') } finally { // Clear busy on both paths so a session that does not flip the gate (for example a refresh // that returns no active session) leaves the form usable instead of a stuck disabled button. setBusy(false) } } async function onActivate(e: React.FormEvent) { e.preventDefault() setErr('') setBusy(true) try { await authApi.mfaActivate(code.trim()) await refresh() } catch { setErr('Invalid code. Make sure the time on your authenticator is correct.') } finally { setBusy(false) } } return (
missionMATCHâ„¢
{step === 'credentials' && (

Sign in

{err &&

{err}

} } label="Continue" /> )} {step === 'verify' && (

Two factor authentication

{useRecovery ? 'Enter one of your single use recovery codes.' : 'Enter the 6 digit code from your authenticator app.'}

{err &&

{err}

} } label="Verify" /> )} {step === 'enroll' && enroll && (

Set up two factor authentication

Add this account to your authenticator app, then enter the 6 digit code it shows. MFA is required for every account.

Setup key
{enroll.secret}
Open in authenticator
{err &&

{err}

} } label="Activate and sign in" /> )}

Powered by the Adaptive Intelligence Optimization Engineâ„¢

) } function Field({ label, value, onChange, type = 'text', autoFocus, maxLength, }: { label: string value: string onChange: (v: string) => void type?: string autoFocus?: boolean maxLength?: number }) { return ( ) } function Submit({ busy, icon, label }: { busy: boolean; icon: React.ReactNode; label: string }) { return ( ) }