spinny:~/writing $ vim passkeys-webauthn-passwordless-authentication.md
1~2Passwö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.3~4Die 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.5~6## Was wirklich passiert7~8Ein passkey ist ein Berechtigungsnachweis, der auf WebAuthn basiert. Wenn der Benutzer es erstellt, generiert das Gerät ein Schlüsselpaar:9~10- ein privater Schlüssel, der auf dem Gerät oder im Passwort-Manager verbleibt;11- ein öffentlicher Schlüssel, den der Server speichern kann.12~13Beim 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.14~15Das 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.16~17## Der Browser fungiert als Brücke18~19Im Browser sind die beiden wichtigsten API:20~21- `navigator.credentials.create()`, um ein passkey zu erstellen;22- `navigator.credentials.get()`, um es während der Anmeldung zu verwenden.23~24Aber 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.25~26Der Client-Teil dürfte fast langweilig sein:27~28```typescript29const options = await fetch('/api/passkeys/login/options').then((r) => r.json());30~31const credential = await navigator.credentials.get({32 publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options),33});34~35await fetch('/api/passkeys/login/verify', {36 method: 'POST',37 headers: { 'Content-Type': 'application/json' },38 body: JSON.stringify(credential?.toJSON()),39});40```41~42Wenn 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.43~44## Was in der Datenbank gespeichert werden soll45~46Es besteht keine Notwendigkeit, die halbe Welt zu retten. Normalerweise reicht:47~48- ID des Ausweises;49- öffentlicher Schlüssel;50- verbundener Benutzer;51- etwaige Verifizierungszähler oder Metadaten;52- Transporte, sofern für die UX nützlich;53- vom Benutzer gewählter Name;54- Erstellungsdatum und letzte Verwendung.55~56Eine minimale Tabelle könnte so aussehen:57~58```sql59create table passkey_credentials (60 id uuid primary key default gen_random_uuid(),61 user_id uuid not null references users(id),62 credential_id text not null unique,63 public_key text not null,64 name text,65 created_at timestamptz not null default now(),66 last_used_at timestamptz67);68```69~70Dann 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.71~72## UX ist wichtiger als Demo73~74Die Demo eines passkey ist immer schön: Du klickst, Face ID, schon bist du dabei. Das eigentliche Produkt ist komplizierter.75~76Jemand 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.77~78Deshalb würde ich nicht mit „ab heute keine Passwörter mehr für alle“ beginnen. Ich würde so beginnen:79~801. passkey optional für interne Benutzer;812. Vorschlag, nach erfolgreicher Anmeldung eines zu erstellen;823. Kontoseite zum Umbenennen und Entfernen passkey;834. klarer Fallback;845. Schrittweiser Rollout im Haupt-Login.85~86Der Text in der Benutzeroberfläche sollte einfach sein. „Verwenden Sie den Sperrbildschirm Ihres Geräts“ ist besser als „Authentifizierung mit einem residenten FIDO2-Anmeldedatensatz“.87~88## Fehler, die ich vermeiden würde89~90Stellen Sie den Kunden nicht vor Herausforderungen. Die Challenge wird auf dem Server erstellt und muss nur einmal verifiziert werden.91~92Vertrauen Sie nicht nur der Anmeldeinformations-ID. Sie müssen Signatur, Challenge, Herkunft und Relying Party ID überprüfen.93~94Lö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“.95~96Behandeln Sie die passkey nicht als reine Frontend-Schaltfläche. Das Ausblenden einer Schaltfläche stellt keine Sicherheit dar: Die eigentliche Überprüfung erfolgt serverseitig.97~98## Passkey-first oder passkey-freundlich?99~100Bei 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.101~102Die 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.103~104## Fazit105~106Die 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.107~108Aber 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.109~110## Quellen111~112- [MDN: Passkeys](https://developer.mozilla.org/en-US/docs/Web/Security/Authentication/Passkeys)113- [MDN: Web Authentication API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API)114- [W3C: Web Authentication](https://www.w3.org/TR/webauthn-3/)115- [passkeys.dev](https://passkeys.dev/)116~
NORMAL · passkeys-webauthn-passwordless-authentication.md [readonly]116 lines · :q to close