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. Die Umstellung von der passwortbasierten auf die passkeybasierte Authentifizierung kann jedoch die Nutzerfreundlichkeit beeinträchtigen. Wenn Sie Passkeys mithilfe der Autofill-Funktion für Formulare vorschlagen, kann das die Nutzerfreundlichkeit verbessern.
Warum sollte ich die Autofill-Funktion für Formulare verwenden, um mich mit einem Passkey anzumelden?
Mit einem Passkey kann sich ein Nutzer mit seinem Fingerabdruck, seinem Gesicht oder der PIN seines Geräts auf einer Website anmelden.
Idealerweise gibt es keine Passwortnutzer und der Authentifizierungsablauf könnte so einfach wie eine Schaltfläche für die Einmalanmeldung sein. Wenn der Nutzer auf die Schaltfläche tippt, wird ein Kontoauswahldialogfeld angezeigt. Der Nutzer kann ein Konto auswählen, den Bildschirm entsperren, um sich zu authentifizieren und anzumelden.
Die Umstellung von der Passwort- zur Passkey-basierten Authentifizierung kann jedoch schwierig sein. Auch wenn Nutzer zu Passkeys wechseln, werden immer noch einige Passwörter verwenden. Websites müssen also beide Nutzertypen unterstützen. Nutzer sollten sich nicht merken müssen, auf welchen Websites sie zu Passkeys gewechselt sind. Daher wäre es nicht nutzerfreundlich, wenn sie vorab auswählen müssten, welche Methode verwendet werden soll.
Passkeys sind ebenfalls eine neue Technologie. Sie zu erklären und dafür zu sorgen, dass Nutzer sie problemlos verwenden können, kann eine Herausforderung für Websites sein. Wir können auf vertraute Nutzererfahrungen beim automatischen Ausfüllen von Passwörtern zurückgreifen, um beide Probleme zu lösen.
Bedingte Benutzeroberfläche
Um die Nutzerfreundlichkeit sowohl für Passkey- als auch für Passwortnutzer zu verbessern, können Sie Passkeys in Autofill-Vorschläge aufnehmen. Diese Funktion wird als Bedingte Benutzeroberfläche bezeichnet und ist Teil des WebAuthn-Standards.
Sobald der Nutzer auf das Eingabefeld für den Nutzernamen tippt, wird ein Dialogfeld mit Vorschlägen zur automatischen Vervollständigung angezeigt, in dem die gespeicherten Passkeys zusammen mit Vorschlägen zur automatischen Passwortvervollständigung hervorgehoben werden. Der Nutzer kann dann ein Konto auswählen und sich über die 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: Das Frontend kommuniziert mit dem Browser und sendet Abrufanfragen an das Backend.
- Browser: Der Browser des Nutzers, in dem Ihr JavaScript ausgeführt wird.
- Authenticator: Der Authenticator des Nutzers, der den Passkey erstellt und speichert. Das kann auf demselben Gerät wie der Browser sein (z. B. bei der Verwendung von Windows Hello) oder auf einem anderen Gerät wie einem Smartphone.
- Sobald ein Nutzer das Frontend aufruft, wird vom Backend eine Herausforderung angefordert, um sich mit einem Passkey zu authentifizieren. Daraufhin wird
navigator.credentials.get()
aufgerufen, um die Authentifizierung mit einem Passkey zu starten. Dies gibt einePromise
zurück. - Wenn der Nutzer den Mauszeiger in das Anmeldefeld bewegt, zeigt der Browser ein Dialogfeld für die Passwort-Autofill mit Passkeys an. 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 Backend prüft die Signatur anhand des öffentlichen Schlüssels des übereinstimmenden Kontos in der Datenbank. Wenn der Vorgang erfolgreich war, ist der Nutzer angemeldet.
Über die Funktion „Autofill“ mit einem Passkey authentifizieren
Wenn sich ein Nutzer anmelden möchte, können Sie einen bedingten WebAuthn-get
-Aufruf senden, 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 statt durch Ausfüllen des Anmeldeformulars. Die Seite ist dann dafür verantwortlich, den Nutzer anzumelden.
Eingabefeld für das Formular annotieren
Fügen Sie dem Feld „Nutzername“ input
ggf. das Attribut autocomplete
hinzu.
Fügen Sie username
und webauthn
als Tokens hinzu, damit Passkeys vorgeschlagen werden.
<input type="text" name="username" autocomplete="username webauthn" ...>
Funktionserkennung
Bevor Sie einen bedingten WebAuthn API-Aufruf ausführen, prüfen Sie Folgendes:
- Der Browser unterstützt WebAuthn mit
PublicKeyCredential
.
- Der Browser unterstützt die WebAuthn-Bedingte Benutzeroberfläche 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
}
}
Eine Herausforderung vom RP-Server abrufen
Rufe eine Herausforderung vom RP-Server ab, die für den Aufruf von navigator.credentials.get()
erforderlich ist:
challenge
: Eine servergenerierte Herausforderung in einem ArrayBuffer. Dies ist erforderlich, um Wiederholungsversuche zu verhindern. Achten Sie darauf, bei jedem Anmeldeversuch eine neue Herausforderung zu generieren und sie nach einer bestimmten Zeit oder nach einem fehlgeschlagenen Anmeldeversuch zu ignorieren. Sie können es sich als CSRF-Token vorstellen.allowCredentials
: Ein Array zulässiger Anmeldedaten für diese Authentifizierung. Übergeben Sie ein leeres Array, damit der Nutzer einen verfügbaren Passkey aus einer Liste auswählen kann, die vom Browser angezeigt wird.userVerification
: Gibt an, ob die Nutzerbestätigung über die Displaysperre des Geräts"required"
,"preferred"
oder"discouraged"
ist. Die Standardeinstellung ist"preferred"
. Das bedeutet, dass der Authenticator die Nutzerbestätigung möglicherweise überspringt. Legen Sie dafür"preferred"
fest oder lassen Sie das Attribut weg.
WebAuthn API mit dem Flag conditional
aufrufen, um den Nutzer zu authentifizieren
Rufe 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 registrierbares Suffix angeben. Dieser Wert muss mit der rp.id übereinstimmen, die beim Erstellen des Passkeys verwendet wurde.
Geben Sie mediation: 'conditional'
an, um die Anfrage bedingt zu machen.
Die zurückgegebenen Public-Key-Anmeldedaten an den 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. Je nach name
-Eigenschaft des Error
-Objekts müssen Sie die Fehler entsprechend behandeln:
NotAllowedError
: Der Nutzer hat den Vorgang abgebrochen.- Andere Ausnahmen: Ein unerwarteter Fehler ist aufgetreten. Der Browser zeigt dem Nutzer ein Fehlerdialogfeld an.
Das Objekt „Public-Key-Anmeldedaten“ enthält die folgenden Eigenschaften:
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 von 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 enthält, 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 der Nutzer ein Smartphone zur Anmeldung verwenden musste, können Sie ihn auffordern, einen Passkey auf dem lokalen Gerät 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.
Rufen Sie die übereinstimmende Anmeldedaten-ID mit der Property id
ab. Wenn Sie das Nutzerkonto ermitteln möchten, verwenden Sie die Property userHandle
, also die user.id
, die Sie beim Erstellen der Anmeldedaten angegeben haben. Prüfen Sie, ob die signature
der Anmeldedaten mit dem gespeicherten öffentlichen Schlüssel verifiziert werden kann. Wir empfehlen, dafür eine serverseitige Bibliothek oder Lösung zu verwenden, anstatt eigenen Code zu schreiben. Open-Source-Bibliotheken finden Sie im GitHub-Repository von 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.