Mit einem Passkey über die Funktion „Autofill“ anmelden

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 Formularautofill-Funktion vorschlagen, kann dies zu einer einheitlichen Nutzererfahrung beitragen.

Warum sollte ich die Formularautofill-Funktion 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 es immer noch Nutzer geben, die 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 keine gute UX, Nutzer vorab zu bitten, die zu verwendende Methode auszuwählen.

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.
Diagramm zur Passkey-Authentifizierung
  1. 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 eine Promise zurück.
  2. 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.
  3. 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.
  4. 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 Formularautofill 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.

Unterstützte Browser

  • Chrome: 67.
  • Edge: 18.
  • Firefox: 60.
  • Safari: 13.

Quelle

Unterstützte Browser

  • Chrome: 108.
  • Edge: 108.
  • Firefox: 119.
  • Safari: 16.

Quelle

// 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: Gibt platform zurück, wenn diese Anmeldedaten vom lokalen Gerät stammen. Andernfalls cross-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.

Ressourcen