Passkey für Anmeldungen ohne Passwort erstellen

Passkeys machen Nutzerkonten sicherer und einfacher.

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

Ein Passkey muss erstellt, einem Nutzerkonto zugeordnet und der öffentliche Schlüssel auf Ihrem Server gespeichert werden, bevor sich ein Nutzer damit anmelden kann.

Funktionsweise

Nutzer können in einer der folgenden Situationen aufgefordert werden, einen Passkey zu erstellen:

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

Verwenden Sie zum Erstellen eines Passkeys die WebAuthn API.

Die vier Komponenten der Passkey-Registrierung sind:

  • Back-End: Ihr Back-End-Server, auf dem die Kontendatenbank gespeichert ist, 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 können 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-Registrierung

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

  1. Ein Nutzer meldet sich auf der Website an.
  2. Sobald der Nutzer angemeldet ist, fordert er die Erstellung eines Passkeys im Frontend an, z. B. durch Klicken auf die Schaltfläche „Passkey erstellen“.
  3. Das Frontend fordert Informationen vom Backend an, um einen Passkey zu erstellen, z. B. Nutzerinformationen, eine Identitätsbestätigung und die auszuschließenden Anmeldedaten-IDs.
  4. Das Front-End ruft navigator.credentials.create() auf, um einen Passkey zu erstellen. Dieser Aufruf gibt ein Promise zurück.
  5. Ein Passkey wird erstellt, nachdem der Nutzer über die Displaysperre des Geräts eingewilligt hat. Das Promise wird aufgelöst und die Anmeldedaten für einen öffentlichen Schlüssel werden an das Front-End 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 dem Nutzerkonto für zukünftige Authentifizierungen zugeordnet ist.

Kompatibilitäten

WebAuthn wird von den meisten Browsern unterstützt, aber es gibt kleine Lücken. Unter Gerätesupport – passkeys.dev erfahren Sie, welche Kombination von Browsern und Betriebssystemen die Erstellung von Passkeys unterstützt.

Neuen Passkey erstellen

Im Folgenden wird beschrieben, wie ein Front-End bei einer Anfrage zum Erstellen eines neuen Passkeys verarbeitet wird.

Funktionserkennung

Bevor die Schaltfläche „Neuen Passkey erstellen“ angezeigt wird, prüfen Sie, ob Folgendes zutrifft:

  • Der Browser unterstützt WebAuthn.
  • Das Gerät unterstützt einen Plattformauthentifizierungsmechanismus (kann einen Passkey erstellen und sich mit dem Passkey authentifizieren).
  • Der Browser unterstützt die bedingte WebAuthn-UI.
// 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  
    }  
  });  
}  

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

Wichtige Informationen aus dem Backend abrufen

Wenn der Nutzer auf die Schaltfläche klickt, rufen Sie wichtige Informationen zum Aufrufen von navigator.credentials.create() aus dem Back-End ab:

  • challenge: Eine servergenerierte Herausforderung in ArrayBuffer für diese Registrierung. Dies ist erforderlich, wird aber während der Registrierung nicht verwendet, sofern keine Attestierung durchgeführt wird. 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 16-Byte-Wert, der pro Konto generiert wird, eignet sich gut.
  • user.name: Dieses Feld sollte eine eindeutige Kennung für das Konto enthalten, das der Nutzer erkennt, z. B. seine E-Mail-Adresse oder seinen Nutzernamen. Dies wird in der Kontoauswahl angezeigt. (Wenn Sie einen Nutzernamen verwenden, verwenden Sie denselben Wert wie bei der Passwortauthentifizierung.)
  • user.displayName: Dieses Feld ist ein Pflichtfeld und nutzerfreundlicherer Name für das Konto. Er muss nicht eindeutig sein und kann der vom Nutzer gewählte Name sein. Wenn es auf Ihrer Website keinen geeigneten Wert gibt, den Sie hier aufnehmen können, übergeben Sie einen leeren String. Dies kann je nach Browser in der Kontoauswahl angezeigt werden.
  • excludeCredentials: Verhindert die Registrierung desselben Geräts, indem eine Liste bereits registrierter Anmeldedaten-IDs bereitgestellt wird. Das transports-Mitglied sollte, sofern angegeben, das Ergebnis des Aufrufs von getTransports() während der Registrierung der einzelnen Anmeldedaten enthalten.

WebAuthn API aufrufen, um einen Passkey zu erstellen

Rufe navigator.credentials.create() auf, um einen neuen Passkey zu erstellen. Die API gibt ein Promise zurück und wartet auf die Interaktion des Nutzers. Es wird ein modales Dialogfeld angezeigt.

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 erläuterten Parameter sind:

  • rp.id: Eine RP-ID ist eine Domain und für eine Website kann entweder ihre Domain oder ein registrierbares Suffix angegeben werden. Wenn der Ursprung einer 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 einer beliebigen Subdomain unter example.com authentifizieren.

  • rp.name: Der Name des RP.

  • pubKeyCredParams: Dieses Feld gibt die vom RP unterstützten öffentlichen Schlüsselalgorithmen an. Wir empfehlen, ihn auf [{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. Damit ist eine vollständige Abdeckung möglich.

  • authenticatorSelection.authenticatorAttachment: Setzen Sie diesen Wert auf "platform", wenn diese Passkey-Erstellung ein Upgrade von einem Passwort ist, z.B. bei einer Hochstufung nach einer Anmeldung. "platform" gibt an, dass das RP eine Plattformauthentifizierungs-App (einen in das Plattformgerät eingebetteten Authenticator) möchte, der nicht zum Einstecken z.B. eines USB-Sicherheitsschlüssels auffordert. Der Nutzer hat eine einfachere Option, um einen Passkey zu erstellen.

  • authenticatorSelection.requireResidentKey: Legen Sie den booleschen Wert "true" fest. Mit erkennbaren Anmeldedaten (Residenzschlüssel) werden Nutzerinformationen im Passkey gespeichert. Nutzer können das Konto bei der Authentifizierung auswählen.

  • authenticatorSelection.userVerification: Gibt an, ob die Nutzerbestätigung über die Displaysperre des Geräts "required", "preferred" oder "discouraged" ist. Der Standardwert ist "preferred", was bedeutet, dass der Authenticator die Nutzerbestätigung möglicherweise überspringen kann. Legen Sie dafür "preferred" fest oder lassen Sie das Attribut weg.

Zurückgegebene Anmeldedaten für den öffentlichen Schlüssel an das Backend senden

Nachdem der Nutzer über die Displaysperre des Geräts seine Einwilligung gegeben hat, wird ein Passkey erstellt und das Promise aufgelöst, das ein PublicKeyCredential-Objekt an das Front-End zurückgibt.

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

  • InvalidStateError: Auf dem Gerät ist bereits ein Passkey vorhanden. Dem Nutzer wird kein Fehlerdialog angezeigt und die Website sollte dies nicht als Fehler behandeln – der Nutzer wollte, dass das lokale Gerät registriert wird, und das ist es auch.
  • NotAllowedError: Der Nutzer hat den Vorgang abgebrochen.
  • Weitere Ausnahmen: Ein unerwarteter Fehler ist aufgetreten. Der Browser zeigt dem Nutzer ein Fehlerdialogfeld an.

Das Anmeldedatenobjekt für den öffentlichen Schlüssel 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 ein übereinstimmender Passkey im Gerät befindet. Dieser Wert muss in der Datenbank auf dem Back-End gespeichert werden.
  • rawId: Eine ArrayBuffer-Version der Anmeldedaten-ID.
  • response.clientDataJSON: ArrayBuffer-codierte Clientdaten
  • response.attestationObject: Ein ArrayBuffer-codiertes Attestierungsobjekt. Diese enthält wichtige Informationen wie eine RP-ID, Flags und einen öffentlichen Schlüssel.
  • authenticatorAttachment: Gibt "platform" zurück, wenn diese Anmeldedaten auf einem Passkey-fähigen Gerät erstellt werden.
  • type: Dieses Feld ist immer auf "public-key" gesetzt.

Wenn Sie eine Bibliothek zur Verarbeitung des Public-Key-Anmeldedatenobjekts im Back-End verwenden, empfehlen wir, das gesamte Objekt nach der teilweisen Codierung mit base64url an das Back-End zu senden.

Anmeldedaten speichern

Wenn Sie die Anmeldedaten für den öffentlichen Schlüssel im Back-End erhalten, übergeben Sie diese an die FIDO-Bibliothek, um das Objekt zu verarbeiten.

Anschließend können Sie die aus den Anmeldedaten abgerufenen Informationen zur späteren Verwendung in der Datenbank speichern. Die folgende Liste enthält einige typische Eigenschaften, die gespeichert werden sollten:

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

Die Anmeldedaten mit öffentlichem Schlüssel enthalten auch die folgenden Informationen, die Sie in der Datenbank speichern sollten:

Weitere Informationen zum Authentifizieren des Nutzers finden Sie unter Mit einem Passkey über Autofill für Formulare anmelden.

Ressourcen