Erstellen Sie eine Anmeldeumgebung, die Passkeys verwendet und gleichzeitig bestehende Passwortnutzer unterstützt.
Passkeys ersetzen Passwörter und machen Nutzerkonten im Web sicherer, einfacher und nutzerfreundlicher. Der Wechsel von der passwortbasierten zur Passkey-basierten Authentifizierung kann jedoch die Nutzererfahrung erschweren. Durch die Autofill-Funktion von Formularen zum Vorschlagen von Passkeys lässt sich eine einheitliche Nutzererfahrung schaffen.
Warum sollten Sie die Autofill-Funktion für Formulare verwenden, um sich mit einem Passkey anzumelden?
Mit einem Passkey können sich Nutzer einfach per Fingerabdruck, Gesichtserkennung oder Geräte-PIN auf einer Website anmelden.
Im Idealfall gibt es keine Passwortnutzer und der Authentifizierungsvorgang könnte so einfach wie eine einzelne Anmeldeschaltfläche sein. Wenn der Nutzer auf die Schaltfläche tippt, wird ein Dialogfeld zur Kontoauswahl angezeigt, in dem er ein Konto auswählen und den Bildschirm entsperren und sich anmelden kann.
Die Umstellung von der passwortbasierten zur Passkey-basierten Authentifizierung kann jedoch eine Herausforderung sein. Wenn Nutzer zu Passkeys wechseln, müssen sie weiterhin beide Arten von Nutzern berücksichtigen, die Passwörter und Websites verwenden. Von Nutzern selbst sollte nicht erwartet werden, dass sie sich merken, auf welchen Websites sie auf Passkeys umgestellt haben. Daher wäre es nicht sinnvoll, die Nutzer aufzufordern, die Methode vorab auszuwählen.
Passkeys sind ebenfalls eine neue Technologie. Es kann für Websites schwierig sein, sie zu erklären und ihnen zu vermitteln, dass sie keine Bedenken haben. Beide Probleme lassen sich mithilfe der vertrauten Benutzeroberfläche zum automatischen Ausfüllen von Passwörtern lösen.
Bedingte Benutzeroberfläche
Sie können Passkeys in Autofill-Vorschläge aufnehmen, um sowohl Passkeys als auch Passwortnutzern eine effiziente Nutzung zu ermöglichen. Dies wird als bedingte UI bezeichnet und ist Teil des WebAuthn-Standards.
Sobald der Nutzer auf das Eingabefeld für den Nutzernamen tippt, wird ein Dialogfeld mit einem Autofill-Vorschlag angezeigt, in dem die gespeicherten Passkeys und Vorschläge zum automatischen Ausfüllen von Passwörtern hervorgehoben werden. Der Nutzer kann dann ein Konto auswählen und sich mit der Displaysperre des Geräts anmelden.
Auf diese Weise können sich Nutzer mit dem vorhandenen Formular auf Ihrer Website anmelden, als wäre nichts geändert worden. Sie erhalten jedoch den zusätzlichen Sicherheitsvorteil von Passkeys, falls sie einen haben.
Funktionsweise
Für die Authentifizierung mit einem Passkey verwenden Sie die WebAuthn API.
Die vier Komponenten eines Passkey-Authentifizierungsablaufs sind: der Nutzer:
- Back-End: Ihr Back-End-Server, auf dem sich die Kontendatenbank befindet, in der der öffentliche Schlüssel und andere Metadaten zum Passkey gespeichert sind.
- Frontend: Ihr Frontend, das mit dem Browser kommuniziert und Abrufanfragen an das Backend sendet
- Browser: Der Browser des Nutzers, in dem Ihr JavaScript ausgeführt wird.
- Authenticator: Der Authenticator des Nutzers, der den Passkey erstellt und speichert. Diese kann sich auf demselben Gerät wie der Browser (z.B. bei Verwendung von Windows Hello) oder auf einem anderen Gerät wie einem Smartphone befinden.
![Diagramm zur Passkey-Authentifizierung](https://web.dev/static/articles/passkey-form-autofill/image/passkey-authentication-diagram.png?authuser=5&hl=de)
- Sobald ein Nutzer auf dem Frontend landet, fordert er vom Backend eine Aufforderung zur Authentifizierung mit einem Passkey an und ruft
navigator.credentials.get()
auf, um die Authentifizierung mit einem Passkey zu starten. Dies gibt einPromise
zurück. - Wenn der Nutzer den Cursor in das Anmeldefeld platziert, zeigt der Browser ein Dialogfeld zum automatischen Ausfüllen von Passwörtern an, das Passkeys enthält. Wenn der Nutzer einen Passkey auswählt, wird ein Authentifizierungsdialogfeld angezeigt.
- Nachdem der Nutzer seine Identität mithilfe der Displaysperre des Geräts bestätigt hat, wird das Versprechen aufgelöst und die Anmeldedaten mit einem öffentlichen Schlüssel werden an das Front-End zurückgegeben.
- Das Frontend sendet die Anmeldedaten für den öffentlichen Schlüssel an das Backend. Das Back-End überprüft die Signatur anhand des öffentlichen Schlüssels des übereinstimmenden Kontos in der Datenbank. Ist sie erfolgreich, ist der Nutzer angemeldet.
Über die Funktion „Autofill“ mit einem Passkey authentifizieren
Wenn sich ein Nutzer anmelden möchte, können Sie einen bedingten get
-Aufruf von WebAuthn ausführen, um anzugeben, dass Passkeys in Autofill-Vorschlägen enthalten sein können. Bei einem bedingten Aufruf der navigator.credentials.get()
API von WebAuthn wird die Benutzeroberfläche nicht angezeigt. Er bleibt ausstehend, bis der Nutzer über die Autofill-Vorschläge ein Konto für die Anmeldung auswählt. Wenn der Nutzer einen Passkey auswählt, löst der Browser das Versprechen mit Anmeldedaten auf, anstatt das Anmeldeformular auszufüllen. Dann ist die Seite für die Anmeldung
des Nutzers verantwortlich.
Eingabefeld für Formular hinzufügen
Fügen Sie bei Bedarf ein autocomplete
-Attribut im Feld für den Nutzernamen input
hinzu.
Hängen Sie username
und webauthn
als Tokens an, damit Passkeys vorgeschlagen werden.
<input type="text" name="username" autocomplete="username webauthn" ...>
Funktionserkennung
Prüfen Sie vor dem Aufrufen eines bedingten WebAuthn API-Aufrufs Folgendes:
- Der Browser unterstützt WebAuthn mit
PublicKeyCredential
.
- Der Browser unterstützt die bedingte WebAuthn-UI mit
PublicKeyCredenital.isConditionalMediationAvailable()
.
// Availability of `window.PublicKeyCredential` means WebAuthn is usable.
if (window.PublicKeyCredential &&
PublicKeyCredential.isConditionalMediationAvailable) {
// Check if conditional mediation is available.
const isCMA = await PublicKeyCredential.isConditionalMediationAvailable();
if (isCMA) {
// Call WebAuthn authentication
}
}
Herausforderung vom RP-Server abrufen
Rufen Sie vom RP-Server eine Aufgabe ab, die zum Aufrufen von navigator.credentials.get()
erforderlich ist:
challenge
: Eine vom Server generierte Abfrage in einem ArrayBuffer. Dies ist erforderlich, um Replay-Angriffe zu verhindern. Bei jedem Anmeldeversuch muss eine neue Identitätsbestätigung generiert werden. Ignorieren Sie diese nach einer bestimmten Dauer oder nach fehlgeschlagenen Anmeldeversuchen. Betrachten Sie es wie ein CSRF-Token.allowCredentials
: Ein Array zulässiger Anmeldedaten für diese Authentifizierung. Übergeben Sie ein leeres Array, damit der Nutzer einen verfügbaren Passkey aus einer vom Browser angezeigten Liste auswählen kann.userVerification
: Gibt an, ob die Nutzerbestätigung mithilfe der Displaysperre des Geräts"required"
,"preferred"
oder"discouraged"
ist. Der Standardwert ist"preferred"
. Das bedeutet, dass der Authenticator die Nutzerbestätigung überspringen kann. Legen Sie dafür"preferred"
fest oder lassen Sie das Attribut weg.
WebAuthn API mit dem Flag conditional
aufrufen, um den Nutzer zu authentifizieren
Rufen Sie navigator.credentials.get()
auf, um auf die Nutzerauthentifizierung zu warten.
// To abort a WebAuthn call, instantiate an `AbortController`.
const abortController = new AbortController();
const publicKeyCredentialRequestOptions = {
// Server generated challenge
challenge: ****,
// The same RP ID as used during registration
rpId: 'example.com',
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal,
// Specify 'conditional' to activate conditional UI
mediation: 'conditional'
});
rpId
: Eine RP-ID ist eine Domain und eine Website kann entweder ihre Domain oder ein registrierfähiges Suffix angeben. Dieser Wert muss mit der rp.id übereinstimmen, die beim Erstellen des Passkeys verwendet wurde.
Denken Sie daran, mediation: 'conditional'
anzugeben, damit die Anfrage bedingt wird.
Zurückgegebene Anmeldedaten mit öffentlichem Schlüssel an RP-Server senden
Nachdem der Nutzer ein Konto ausgewählt und seine Einwilligung über die Displaysperre des Geräts erteilt hat, wird das Promise aufgelöst und das Objekt PublicKeyCredential
wird an das RP-Front-End zurückgegeben.
Ein Promise kann aus verschiedenen Gründen abgelehnt werden. Sie müssen die Fehler entsprechend dem Attribut name
des Error
-Objekts verarbeiten:
NotAllowedError
: Der Nutzer hat den Vorgang abgebrochen.- Andere Ausnahmen: Ein unerwarteter Fehler ist aufgetreten. Im Browser wird dem Nutzer ein Fehlerdialogfeld angezeigt.
Das Anmeldedatenobjekt für den öffentlichen Schlüssel enthält die folgenden Attribute:
id
: Die base64url-codierte ID der authentifizierten Passkey-Anmeldedaten.rawId
: Eine ArrayBuffer-Version der Anmeldedaten-ID.response.clientDataJSON
: Ein ArrayBuffer von Kundendaten. Dieses Feld enthält Informationen wie die Aufgabe und den Ursprung, den der RP-Server überprüfen muss.response.authenticatorData
: Ein ArrayBuffer mit Authentifikatordaten. Dieses Feld enthält Informationen wie die RP-ID.response.signature
: Ein ArrayBuffer der Signatur. Dieser Wert ist der Kern der Anmeldedaten und muss auf dem Server verifiziert werden.response.userHandle
: Ein ArrayBuffer, der die Nutzer-ID enthielt, die bei der Erstellung festgelegt wurde. Dieser Wert kann anstelle der Anmeldedaten-ID verwendet werden, wenn der Server die verwendeten ID-Werte auswählen muss oder wenn das Back-End keinen Index für Anmeldedaten-IDs erstellen möchte.authenticatorAttachment
: Gibtplatform
zurück, wenn diese Anmeldedaten vom lokalen Gerät stammen. Andernfallscross-platform
, insbesondere wenn der Nutzer sich mit einem Smartphone angemeldet hat. Wenn sich der Nutzer mit einem Smartphone anmelden muss, kannst du ihn auffordern, auf dem lokalen Gerät einen Passkey zu erstellen.type
: Dieses Feld ist immer auf"public-key"
gesetzt.
Wenn Sie das Anmeldedatenobjekt mit öffentlichem Schlüssel auf dem RP-Server mithilfe einer Bibliothek verarbeiten, sollten Sie das gesamte Objekt an den Server senden, nachdem Sie es teilweise mit base64url codiert haben.
Überprüfen Sie die Signatur
Wenn Sie die Anmeldedaten mit öffentlichem Schlüssel vom Server erhalten, übergeben Sie sie an die FIDO-Bibliothek, damit das Objekt verarbeitet werden kann.
Suchen Sie die zugehörige Anmeldedaten-ID mit dem Attribut id
. Wenn Sie das Nutzerkonto ermitteln müssen, verwenden Sie das Attribut userHandle
. Das ist die user.id
, die Sie beim Erstellen der Anmeldedaten angegeben haben. Prüfen Sie, ob der signature
der Anmeldedaten mit dem gespeicherten öffentlichen Schlüssel verifiziert werden kann. Wir empfehlen, dafür eine serverseitige Bibliothek oder eine Lösung zu verwenden, anstatt eigenen Code zu schreiben. Open-Source-Bibliotheken finden Sie im GitHub-Repository "awesome-webauth".
Nachdem die Anmeldedaten mit einem passenden öffentlichen Schlüssel verifiziert wurden, melden Sie den Nutzer an.
Eine ausführlichere Anleitung finden Sie unter Serverseitige Passkey-Authentifizierung.