Passkey für Anmeldungen ohne Passwort erstellen

Passkeys machen Nutzerkonten sicherer, einfacher und nutzerfreundlicher.

Die Verwendung von Passkeys anstelle von Passwörtern ist eine gute Möglichkeit für Websites, ihre Nutzerkonten sicherer, einfacher, nutzerfreundlicher und passwortlos zu machen. Mit einem Passkey kann sich ein Nutzer mit seinem Fingerabdruck, seinem Gesicht oder der PIN seines Geräts auf einer Website oder in einer App anmelden.

Ein Passkey muss erstellt, mit einem Nutzerkonto verknüpft und sein öffentlicher Schlüssel auf Ihrem Server gespeichert werden, bevor sich ein Nutzer damit anmelden kann.

Funktionsweise

In den folgenden Fällen werden Nutzer möglicherweise aufgefordert, einen Passkey zu erstellen:

  • Wenn sich ein Nutzer mit einem Passwort anmeldet.
  • Wenn sich ein Nutzer mit einem Passkey von einem anderen Gerät anmeldet (d. h., authenticatorAttachment ist cross-platform).
  • Auf einer speziellen Seite, auf der Nutzer ihre Passkeys verwalten können.

Zum Erstellen eines Passkeys verwenden Sie die WebAuthn API.

Die vier Komponenten des Registrierungsvorgangs für Passkeys sind:

  • Backend: Ihr Backend-Server, auf dem sich die Kontodatenbank mit dem öffentlichen Schlüssel und anderen Metadaten zum Passkey befindet.
  • 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. Dazu kann der Passwortmanager auf demselben Gerät wie der Browser gehören (z. B. bei der Verwendung von Windows Hello) oder auf einem anderen Gerät wie einem Smartphone.
Diagramm zur Registrierung von Passkeys

So fügen Sie einem vorhandenen Nutzerkonto einen neuen Passkey hinzu:

  1. Ein Nutzer meldet sich auf der Website an.
  2. Nachdem sich der Nutzer angemeldet hat, kann er auf der Frontend-Seite einen Passkey erstellen, z. B. durch Drücken der Schaltfläche „Passkey erstellen“.
  3. Das Frontend fordert Informationen vom Backend an, um einen Passkey zu erstellen, z. B. Nutzerinformationen, eine Herausforderung und die Anmeldedaten-IDs, die ausgeschlossen werden sollen.
  4. Das Front-End ruft navigator.credentials.create() auf, um einen Passkey zu erstellen. Dieser Aufruf gibt ein Versprechen zurück.
  5. Ein Passkey wird erstellt, nachdem der Nutzer über die Displaysperre des Geräts seine Einwilligung gegeben hat. Das Versprechen wird aufgelöst und ein öffentliches Schlüssel-Anmeldedaten wird an das Frontend zurückgegeben.
  6. Das Frontend sendet die Anmeldedaten mit dem öffentlichen Schlüssel an das Backend und speichert die Anmeldedaten-ID und den öffentlichen Schlüssel, der mit dem Nutzerkonto verknüpft ist, für zukünftige Authentifizierungen.

Kompatibilitäten

WebAuthn wird von den meisten Browsern unterstützt, es gibt jedoch kleine Lücken. Unter Gerätesupport – passkeys.dev erfahren Sie, welche Kombination aus Browsern und Betriebssystemen das Erstellen eines Passkeys unterstützt.

Neuen Passkey erstellen

So sollte ein Frontend auf eine Anfrage zum Erstellen eines neuen Passkeys reagieren:

Funktionserkennung

Bevor die Schaltfläche „Neuen Passkey erstellen“ angezeigt wird, muss Folgendes erfüllt sein:

  • Der Browser unterstützt WebAuthn mit PublicKeyCredential.

Unterstützte Browser

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

Quelle

  • Das Gerät unterstützt eine Plattform-Authentifizierungs-App (kann einen Passkey erstellen und sich damit authentifizieren) mit PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().

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.  
// `isUserVerifyingPlatformAuthenticatorAvailable` means the feature detection is usable.  
// `​​isConditionalMediationAvailable` means the feature detection is usable.  
if (window.PublicKeyCredential &&  
    PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable &&  
    PublicKeyCredential.​​isConditionalMediationAvailable) {  
  // Check if user verifying platform authenticator is available.  
  Promise.all([  
    PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),  
    PublicKeyCredential.​​isConditionalMediationAvailable(),  
  ]).then(results => {  
    if (results.every(r => r === true)) {  
      // Display "Create a new passkey" button  
    }  
  });  
}  

Solange nicht alle Bedingungen erfüllt sind, werden Passkeys in diesem Browser nicht unterstützt. Die Schaltfläche „Neuen Passkey erstellen“ sollte erst dann angezeigt werden.

Wichtige Informationen aus dem Backend abrufen

Wenn der Nutzer auf die Schaltfläche klickt, werden wichtige Informationen abgerufen, um navigator.credentials.create() aus dem Backend aufzurufen:

  • challenge: Eine servergenerierte Herausforderung in ArrayBuffer für diese Registrierung. Dieser ist erforderlich, wird aber bei der Registrierung nicht verwendet, es sei denn, Sie führen eine Attestierung durch. Dies ist ein fortgeschrittenes Thema, das hier nicht behandelt wird.
  • user.id: Die eindeutige ID eines Nutzers. Dieser Wert muss ein ArrayBuffer sein, der keine personenidentifizierbaren Informationen wie E-Mail-Adressen oder Nutzernamen enthält. Ein zufälliger Wert von 16 Byte, der pro Konto generiert wird, ist gut geeignet.
  • user.name: Dieses Feld sollte eine eindeutige Kennung für das Konto enthalten, die der Nutzer erkennt, z. B. seine E-Mail-Adresse oder seinen Nutzernamen. Dieser wird in der Kontoauswahl angezeigt. Wenn Sie einen Nutzernamen verwenden, verwenden Sie denselben Wert wie bei der Passwortauthentifizierung.
  • user.displayName: Dieses Feld ist ein erforderlicher, nutzerfreundlicherer Name für das Konto. Er muss nicht eindeutig sein und kann der vom Nutzer gewählte Name sein. Wenn Ihre Website keinen geeigneten Wert enthält, geben Sie einen leeren String an. Je nach Browser wird diese Option möglicherweise in der Kontoauswahl angezeigt.
  • excludeCredentials: Verhindert die Registrierung desselben Geräts, indem eine Liste der bereits registrierten Anmeldedaten-IDs angegeben wird. Das Mitglied transports sollte, falls angegeben, das Ergebnis des Aufrufs von getTransports() während der Registrierung der einzelnen Anmeldedaten enthalten.

WebAuthn API aufrufen, um einen Passkey zu erstellen

Rufen Sie navigator.credentials.create() auf, um einen neuen Passkey zu erstellen. Die API gibt ein Versprechen zurück, das auf die Interaktion des Nutzers wartet und ein modales Dialogfeld anzeigt.

Unterstützte Browser

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

Quelle

const publicKeyCredentialCreationOptions = {
  challenge: *****,
  rp: {
    name: "Example",
    id: "example.com",
  },
  user: {
    id: *****,
    name: "john78",
    displayName: "John",
  },
  pubKeyCredParams: [{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}],
  excludeCredentials: [{
    id: *****,
    type: 'public-key',
    transports: ['internal'],
  }],
  authenticatorSelection: {
    authenticatorAttachment: "platform",
    requireResidentKey: true,
  }
};

const credential = await navigator.credentials.create({
  publicKey: publicKeyCredentialCreationOptions
});

// Encode and send the credential to the server for verification.  

Die oben nicht beschriebenen Parameter sind:

  • rp.id: Eine RP-ID ist eine Domain und eine Website kann entweder ihre Domain oder ein registrierbares Suffix angeben. Wenn der Ursprung eines RP beispielsweise https://login.example.com:1337 ist, kann die RP-ID entweder login.example.com oder example.com sein. Wenn die RP-ID als example.com angegeben ist, kann sich der Nutzer bei login.example.com oder auf einer beliebigen Subdomain von login.example.com authentifizieren.example.com

  • rp.name: Name des RP.

  • pubKeyCredParams: In diesem Feld werden die unterstützten Public-Key-Algorithmen des RP angegeben. Wir empfehlen, hier [{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}] festzulegen. Damit wird die Unterstützung von ECDSA mit P-256 und RSA PKCS#1 angegeben. Die Unterstützung dieser beiden Verfahren bietet eine vollständige Abdeckung.

  • authenticatorSelection.authenticatorAttachment: Legen Sie diesen Wert auf "platform" fest, wenn die Erstellung dieses Passkeys ein Upgrade von einem Passwort ist, z.B. in einer Werbeaktion nach einer Anmeldung. "platform" gibt an, dass der RP einen Plattform-Authenticator (einen im Plattformgerät eingebetteten Authenticator) benötigt, bei dem nicht aufgefordert wird, z.B. einen USB-Sicherheitsschlüssel einzulegen. Der Nutzer hat eine einfachere Möglichkeit, einen Passkey zu erstellen.

  • authenticatorSelection.requireResidentKey: Legen Sie den Wert auf „true“ fest. In einem auffindbaren Anmeldedatensatz (Resident Key) werden Nutzerinformationen im Passkey gespeichert und Nutzer können das Konto bei der Authentifizierung auswählen. Weitere Informationen zu Anmeldedaten, die für andere sichtbar sind

  • authenticatorSelection.userVerification: Gibt an, ob eine 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.

Die zurückgegebenen Public-Key-Anmeldedaten an das Backend senden

Nachdem der Nutzer über die Displaysperre des Geräts seine Einwilligung erteilt hat, wird ein Passkey erstellt und das Versprechen wird erfüllt, indem ein PublicKeyCredential-Objekt an das Frontend zurückgegeben wird.

Das Versprechen kann aus verschiedenen Gründen abgelehnt werden. Sie können diese Fehler beheben, indem Sie die Eigenschaft name des Error-Objekts prüfen:

  • InvalidStateError: Auf dem Gerät ist bereits ein Passkey vorhanden. Dem Nutzer wird kein Fehlerdialogfeld angezeigt und die Website sollte dies nicht als Fehler behandeln. Der Nutzer wollte, dass das lokale Gerät registriert wird, und das ist der Fall.
  • 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: Eine Base64URL-codierte ID des erstellten Passkeys. Anhand dieser ID kann der Browser bei der Authentifizierung feststellen, ob sich auf dem Gerät ein übereinstimmender Passkey befindet. Dieser Wert muss in der Datenbank im Backend gespeichert werden.
  • rawId: Eine ArrayBuffer-Version der Anmeldedaten-ID.
  • response.clientDataJSON: Clientdaten, die mit ArrayBuffer codiert sind.
  • response.attestationObject: Ein mit ArrayBuffer codiertes Attestierungsobjekt. Diese enthält wichtige Informationen wie eine RP-ID, Flags und einen öffentlichen Schlüssel.
  • authenticatorAttachment: Wird "platform" zurückgegeben, wenn diese Anmeldedaten auf einem Gerät mit Passkey erstellt wurden.
  • type: Dieses Feld ist immer auf "public-key" gesetzt.

Wenn Sie eine Bibliothek zum Verwalten des Public-Key-Anmeldedatenobjekts im Backend verwenden, empfehlen wir, das gesamte Objekt an das Backend zu senden, nachdem es teilweise mit base64url codiert wurde.

Anmeldedaten speichern

Wenn du die Anmeldedaten für den öffentlichen Schlüssel im Backend erhältst, gib sie an die FIDO-Bibliothek weiter, um das Objekt zu verarbeiten.

Sie können die aus den Anmeldedaten abgerufenen Informationen dann für die zukünftige Verwendung in der Datenbank speichern. Die folgende Liste enthält einige typische Eigenschaften, die Sie speichern sollten:

  • Anmeldedaten-ID (Primärschlüssel)
  • Nutzer-ID
  • Öffentlicher Schlüssel

Die Anmeldedaten für den öffentlichen Schlüssel enthalten auch die folgenden Informationen, die Sie in der Datenbank speichern können:

Eine ausführlichere Anleitung finden Sie unter Serverseitige Passkey-Registrierung.

Informationen zur Authentifizierung des Nutzers finden Sie unter Über das automatische Ausfüllen von Formularen mit einem Passkey anmelden.

Ressourcen