"use client"; import { startRegistration } from "@simplewebauthn/browser"; import { useRouter } from "next/navigation"; import { useState } from "react"; import { Card } from "@/components/ui/Card"; import { formatDatumZeit } from "@/lib/format"; import { passkeyLoeschen } from "@/server/actions/passkeys"; export interface PasskeyZeile { id: string; bezeichnung: string; erstelltAm: Date; zuletztAm: Date | null; } export function PasskeyVerwaltung({ passkeys, moeglich, adresse, }: { passkeys: PasskeyZeile[]; moeglich: boolean; adresse: string; }) { const router = useRouter(); const [bezeichnung, setBezeichnung] = useState(""); const [meldung, setMeldung] = useState<{ art: "fehler" | "erfolg"; text: string } | null>(null); const [laeuft, setLaeuft] = useState(false); async function registrieren() { setLaeuft(true); setMeldung(null); try { const optionen = await fetch("/api/auth/passkey/registrieren").then((antwort) => antwort.json()); // Hier öffnet der Browser seine eigene Abfrage (Fingerabdruck, Gesicht, PIN oder Sicherheitsschlüssel). const antwort = await startRegistration({ optionsJSON: optionen }); const ergebnis = await fetch("/api/auth/passkey/registrieren", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ antwort, bezeichnung }), }).then((a) => a.json()); if (ergebnis.fehler) { setMeldung({ art: "fehler", text: ergebnis.fehler }); } else { setMeldung({ art: "erfolg", text: `„${ergebnis.bezeichnung}“ ist hinterlegt.` }); setBezeichnung(""); router.refresh(); } } catch (fehler) { // Abbruch durch den Benutzer ist kein Fehler, sieht aber genauso aus – deshalb neutral formulieren. setMeldung({ art: "fehler", text: fehler instanceof Error && fehler.name === "NotAllowedError" ? "Abgebrochen oder abgelehnt." : "Der Passkey konnte nicht angelegt werden.", }); } finally { setLaeuft(false); } } return ( <> {!moeglich ? (
Über diese Adresse geht es nicht. Passkeys verlangen HTTPS; nur{" "} localhost ist ausgenommen. Aufgerufen wurde {adresse}. Richten Sie einen Reverse Proxy mit Zertifikat ein und tragen Sie die Adresse unter{" "} Einstellungen → System ein.
) : null} {meldung ? (
{meldung.text}
) : null}
setBezeichnung(e.target.value)} placeholder="z. B. Arbeitsrechner oder Telefon" disabled={!moeglich} />
Hilft später beim Wiedererkennen, wenn mehrere hinterlegt sind.