'use client' import { useState, useRef, Suspense } from 'react' import { useRouter, useSearchParams } from 'next/navigation' import { createClient } from '@/lib/supabase/client' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { useToast } from '@/components/ui/use-toast' import { Loader2, ShieldCheck, Copy, Check } from 'lucide-react' export default function MfaEnrollPage() { return ( ) } function MfaEnrollContent() { const [qrCode, setQrCode] = useState(null) const [secret, setSecret] = useState(null) const [factorId, setFactorId] = useState(null) const [code, setCode] = useState('') const [isEnrolling, setIsEnrolling] = useState(false) const [isVerifying, setIsVerifying] = useState(false) const [copied, setCopied] = useState(false) const inputRef = useRef(null) const { toast } = useToast() const router = useRouter() const searchParams = useSearchParams() const supabase = createClient() const returnTo = searchParams.get('returnTo') || '/' const handleEnroll = async () => { setIsEnrolling(true) try { const { data, error } = await supabase.auth.mfa.enroll({ factorType: 'totp', friendlyName: 'gnubok', }) if (error) { toast({ title: 'Kunde inte aktivera 2FA', description: 'Försök igen senare.', variant: 'destructive', }) setIsEnrolling(false) return } setQrCode(data.totp.qr_code) setSecret(data.totp.secret) setFactorId(data.id) // Focus the code input after render setTimeout(() => inputRef.current?.focus(), 100) } catch { toast({ title: 'Kunde inte aktivera 2FA', description: 'Ett oväntat fel uppstod.', variant: 'destructive', }) } finally { setIsEnrolling(false) } } const handleVerify = async (e: React.FormEvent) => { e.preventDefault() if (!factorId || code.length !== 6) return setIsVerifying(true) try { const { data: challenge, error: challengeError } = await supabase.auth.mfa.challenge({ factorId, }) if (challengeError) { toast({ title: 'Verifiering misslyckades', description: 'Kunde inte starta verifiering. Försök igen.', variant: 'destructive', }) setIsVerifying(false) return } const { error: verifyError } = await supabase.auth.mfa.verify({ factorId, challengeId: challenge.id, code, }) if (verifyError) { toast({ title: 'Fel kod', description: 'Kontrollera att koden stämmer och försök igen.', variant: 'destructive', }) setCode('') inputRef.current?.focus() setIsVerifying(false) return } toast({ title: 'Tvåfaktorsautentisering aktiverad', description: 'Ditt konto är nu skyddat med 2FA.', }) router.push(returnTo) router.refresh() } catch { toast({ title: 'Verifiering misslyckades', description: 'Ett oväntat fel uppstod. Försök igen.', variant: 'destructive', }) } finally { setIsVerifying(false) } } const copySecret = async () => { if (!secret) return await navigator.clipboard.writeText(secret) setCopied(true) setTimeout(() => setCopied(false), 2000) } // Step 1: Show enroll button if (!qrCode) { return (

Aktivera tvåfaktorsautentisering

Skydda ditt konto med en autentiseringsapp som Google Authenticator eller Authy

Du behöver en autentiseringsapp på din telefon. Appen genererar en tidsbegränsad kod som du anger vid varje inloggning.

) } // Step 2: Show QR code and verification return (

Skanna QR-koden

Öppna din autentiseringsapp och skanna koden nedan

{/* QR Code */}
{/* Manual secret */}

Kan du inte skanna? Ange denna nyckel manuellt:

{secret}
{/* Verification code */}
setCode(e.target.value.replace(/\D/g, '').slice(0, 6))} required disabled={isVerifying} className="h-11 text-center text-lg tracking-[0.5em] font-mono" />
) }