Passwörter gehören zu den Dingen, die wir normalisiert haben, nur weil wir jahrelang mit ihnen gelebt haben. Benutzer vergessen sie, verwenden sie wieder und schreiben sie an eine Stelle, an der sie nicht hingehören. Teams müssen Resets, Richtlinien, Hashes, Leaks, Phishing und Support verwalten.
Die passkey machen die Authentifizierung nicht perfekt, aber sie beseitigen ein großes Problem: Der Server muss kein Geheimnis mehr für sich behalten, das er mit dem Benutzer teilt.
Was wirklich passiert
Ein passkey ist ein Berechtigungsnachweis, der auf WebAuthn basiert. Wenn der Benutzer es erstellt, generiert das Gerät ein Schlüsselpaar:
- ein privater Schlüssel, der auf dem Gerät oder im Passwort-Manager verbleibt;
- ein öffentlicher Schlüssel, den der Server speichern kann.
Beim Anmelden fragt der Server nicht nach dem Passwort. Senden Sie eine zufällige Herausforderung. Das Gerät signiert es mit dem privaten Schlüssel. Der Server überprüft die Signatur mit dem öffentlichen Schlüssel.
Das ist das Schöne daran: Wenn die Datenbank gestohlen wird, gibt es darin keine Passwörter, die geknackt werden könnten. Und wenn ein Benutzer auf einer gefälschten Domain landet, ist das passkey für diese Domain nicht gültig. Es geht nicht nur um Bequemlichkeit, sondern um einen konkreten Schutz vor Phishing.
Der Browser fungiert als Brücke
Im Browser sind die beiden wichtigsten API:
navigator.credentials.create(), um ein passkey zu erstellen;navigator.credentials.get(), um es während der Anmeldung zu verwenden.
Aber die wichtige Logik liegt auf dem Server. Der Server muss die Challenge generieren, vorübergehend speichern, die Antwort überprüfen, die Quelle überprüfen und Relying Party ID, dann die Sitzung erstellen.
Der Client-Teil dürfte fast langweilig sein:
const options = await fetch('/api/passkeys/login/options').then((r) => r.json()); const credential = await navigator.credentials.get({ publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options), }); await fetch('/api/passkeys/login/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credential?.toJSON()), });
Wenn Sie feststellen, dass Sie die WebAuthn-Verschlüsselung manuell implementieren, hören Sie auf. Verwenden Sie eine robuste serverseitige Bibliothek. Die Fehler hier sind keine „niedlichen Bugs“, sondern Authentifizierungslücken.
Was in der Datenbank gespeichert werden soll
Es besteht keine Notwendigkeit, die halbe Welt zu retten. Normalerweise reicht:
- ID des Ausweises;
- öffentlicher Schlüssel;
- verbundener Benutzer;
- etwaige Verifizierungszähler oder Metadaten;
- Transporte, sofern für die UX nützlich;
- vom Benutzer gewählter Name;
- Erstellungsdatum und letzte Verwendung.
Eine minimale Tabelle könnte so aussehen:
create table passkey_credentials ( id uuid primary key default gen_random_uuid(), user_id uuid not null references users(id), credential_id text not null unique, public_key text not null, name text, created_at timestamptz not null default now(), last_used_at timestamptz );
Dann würde ich Prüfprotokolle und Benachrichtigungen hinzufügen: Wenn jemand ein neues passkey in meinem Konto erstellt, möchte ich darüber Bescheid wissen.
UX ist wichtiger als Demo
Die Demo eines passkey ist immer schön: Du klickst, Face ID, schon bist du dabei. Das eigentliche Produkt ist komplizierter.
Jemand wechselt sein Telefon. Jemand nutzt einen verschlossenen Firmencomputer. Manche Leute verstehen nicht, warum der Browser eine passkey vorschlägt. Jemand verliert den Zugriff auf sein Gerät.
Deshalb würde ich nicht mit „ab heute keine Passwörter mehr für alle“ beginnen. Ich würde so beginnen:
- passkey optional für interne Benutzer;
- Vorschlag, nach erfolgreicher Anmeldung eines zu erstellen;
- Kontoseite zum Umbenennen und Entfernen passkey;
- klarer Fallback;
- Schrittweiser Rollout im Haupt-Login.
Der Text in der Benutzeroberfläche sollte einfach sein. „Verwenden Sie den Sperrbildschirm Ihres Geräts“ ist besser als „Authentifizierung mit einem residenten FIDO2-Anmeldedatensatz“.
Fehler, die ich vermeiden würde
Stellen Sie den Kunden nicht vor Herausforderungen. Die Challenge wird auf dem Server erstellt und muss nur einmal verifiziert werden.
Vertrauen Sie nicht nur der Anmeldeinformations-ID. Sie müssen Signatur, Challenge, Herkunft und Relying Party ID überprüfen.
Löschen Sie keine Fallbacks, bevor Sie über einen guten Wiederherstellungsablauf verfügen. Passwortlos muss nicht heißen: „Wenn du dein Telefon verlierst, bist du für immer draußen“.
Behandeln Sie die passkey nicht als reine Frontend-Schaltfläche. Das Ausblenden einer Schaltfläche stellt keine Sicherheit dar: Die eigentliche Überprüfung erfolgt serverseitig.
Passkey-first oder passkey-freundlich?
Bei einem neuen Produkt können Sie passkey-first denken. Für eine bestehende App bevorzuge ich passkey-freundlich: passkey als empfohlene Methode hinzufügen, Erfolg und Probleme messen und dann in aller Ruhe das Passwortgewicht reduzieren.
Die ideale Migration ist nicht zu spüren. Der Benutzer stellt fest, dass die Anmeldung einfacher ist und nicht, dass das Unternehmen sein Authentifizierungsprotokoll geändert hat.
Fazit
Die passkey sind interessant, weil sie gleichzeitig Sicherheit und UX verbessern, was selten vorkommt. Sie sind kein Zauberstab: Wiederherstellung, Kompatibilität, Support und Rollout müssen noch gut gestaltet werden.
Aber die grundlegende Veränderung ist stark. Hören Sie auf, von Benutzern zu verlangen, Geheimnisse zu erfinden und zu schützen. Sie lassen das Gerät einen kryptografischen Beweis signieren, der an Ihre Domain gebunden ist. Weniger menschliches Gedächtnis, weniger Phishing, weniger Passwort-Resets. Ich würde sagen, es lohnt sich, sie ernst zu nehmen.