Erstellen Sie eine Anmeldefunktion, die Passkeys nutzt 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 eine Herausforderung 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.
So können sich Nutzer mit dem vorhandenen Formular auf Ihrer Website anmelden, als wäre nichts passiert, aber mit dem zusätzlichen Sicherheitsvorteil von Passkeys, sofern 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:
- Backend: Ihr Backend-Server, auf dem sich die Kontodatenbank mit dem öffentlichen Schlüssel und anderen Metadaten zum Passkey befindet.
- 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 über die Displaysperre des Geräts bestätigt hat, wird das Versprechen aufgelöst und ein öffentliches Schlüssel-Anmeldedaten wird an das Frontend 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.
Mit einem Passkey über das Formular-Autofill-System 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. Ein bedingter Aufruf der navigator.credentials.get()
API von WebAuthn zeigt keine Benutzeroberfläche an und bleibt in der Schwebe, bis der Nutzer aus den Vorschlägen für die automatische Vervollständigung ein Konto auswählt, mit dem er sich anmelden möchte. 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
PublicKeyCredential.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 über die Displaysperre seine Einwilligung erteilt hat, wird das Versprechen erfüllt und ein PublicKeyCredential
-Objekt an das RP-Frontend zurückgegeben.
Ein Versprechen 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 mit Clientdaten. Dieses Feld enthält Informationen wie die Herausforderung und den Ursprung, die der RP-Server überprüfen muss.response.authenticatorData
: Ein ArrayBuffer mit Authenticator-Daten. Dieses Feld enthält Informationen wie die RP-ID.response.signature
: Ein ArrayBuffer der Signatur. Dieser Wert ist der Kern des Anmeldedatensatzes und muss auf dem Server überprüft 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 zu verwendenden ID-Werte auswählen muss oder wenn das Backend das Erstellen eines Index für Anmeldedaten-IDs vermeiden 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, auf dem lokalen Gerät einen Passkey zu erstellen.type
: Dieses Feld ist immer auf"public-key"
gesetzt.
Wenn Sie eine Bibliothek zum Verwalten des Public-Key-Anmeldedatenobjekts auf dem RP-Server verwenden, empfehlen wir, das gesamte Objekt an den Server zu senden, nachdem es teilweise mit base64url codiert wurde.
Überprüfen Sie die Signatur
Wenn Sie die Anmeldedaten für den öffentlichen Schlüssel auf dem Server erhalten, geben Sie sie an die FIDO-Bibliothek weiter, um das Objekt zu verarbeiten.
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.
Sobald die Anmeldedaten mit einem übereinstimmenden öffentlichen Schlüssel bestätigt wurden, melden Sie den Nutzer an.
Eine ausführlichere Anleitung finden Sie unter Serverseitige Passkey-Authentifizierung.