'use client' import { useActionState, useEffect, useState } from 'react' import { useFormStatus } from 'react-dom' import { useRouter } from 'next/navigation' import { AlertCircle, Fingerprint, Loader2, ShieldCheck } from 'lucide-react' import { anmeldungBestaetigen, type BestaetigenZustand } from '@/server/actions/bestaetigen' import { passkeyBestaetigen, passkeyBestaetigungStarten } from '@/server/actions/passkey' import { browserSupportsWebAuthn, passkeyBrowserfehler, startAuthentication, } from '@/lib/passkey-browser' import { Alert, AlertDescription } from '@/components/ui/alert' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Feld } from '@/components/feld' function Absenden() { const { pending } = useFormStatus() return ( ) } export function BestaetigenFormular({ weiter, passkeysMoeglich, }: { weiter: string passkeysMoeglich: boolean }) { const [zustand, aktion] = useActionState(anmeldungBestaetigen, {}) return (
{zustand.fehler && ( )} {passkeysMoeglich && }
) } /** * Bestaetigung mit Passkey statt mit Passwort und Code. * * Geprueft wird zusaetzlich, dass der Passkey zum angemeldeten Benutzer * gehoert - sonst koennte jemand mit dem eigenen Finger eine fremde, * offen stehende Sitzung freischalten. Genau der Fall, gegen den diese * Seite gebaut ist. */ function PasskeyBestaetigung({ weiter }: { weiter: string }) { const router = useRouter() const [browserKann, setBrowserKann] = useState(false) const [laeuft, setLaeuft] = useState(false) const [fehler, setFehler] = useState(null) useEffect(() => { setBrowserKann(browserSupportsWebAuthn()) }, []) async function bestaetigen() { setFehler(null) setLaeuft(true) try { const start = await passkeyBestaetigungStarten() if (!start.ok) { setFehler(start.fehler) return } const antwort = await startAuthentication({ optionsJSON: start.optionen }) const ergebnis = await passkeyBestaetigen(JSON.stringify(antwort)) if (!ergebnis.ok) { setFehler(ergebnis.fehler) return } router.replace(weiter) router.refresh() } catch (ausnahme) { setFehler(passkeyBrowserfehler(ausnahme)) } finally { setLaeuft(false) } } if (!browserKann) return null return (
oder
{fehler && ( )}
) }