Passkey für Anmeldungen ohne Passwort erstellen

Passkeys machen Nutzerkonten sicherer, einfacher und nutzerfreundlicher.

Die Verwendung von Passkeys anstelle von Passwörtern bietet Websites die Möglichkeit, ihre Nutzerkonten sicherer, einfacher, nutzerfreundlicher und passwortloser zu gestalten. Mit einem Passkey können sich Nutzer einfach mit ihrem Fingerabdruck, ihrem Gesicht oder ihrer Geräte-PIN auf einer Website oder in einer App anmelden.

Sie müssen einen Passkey erstellen, mit einem Nutzerkonto verknüpfen und seinen öffentlichen Schlüssel auf Ihrem Server speichern, 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 auf einem anderen Gerät anmeldet, also der authenticatorAttachment ist cross-platform.
  • Auf einer eigenen Seite, auf der Nutzer ihre Passkeys verwalten können.

Zum Erstellen eines Passkeys verwenden Sie die WebAuthn API.

Die vier Komponenten der Passkey-Registrierung sind:

  • 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: 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 kann 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 Front-End 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 der Verwendung der Displaysperre des Geräts zugestimmt hat. Das Promise wird aufgelöst und die Anmeldedaten mit einem öffentlichen Schlüssel werden an das Front-End zurückgegeben.
  6. Das Frontend sendet die Anmeldedaten mit öffentlichem Schlüssel an das Backend und speichert die Anmeldedaten-ID und den öffentlichen Schlüssel, die dem Nutzerkonto zugeordnet sind, für zukünftige Authentifizierungen.

Kompatibilitäten

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

Neuen Passkey erstellen

So sollte ein Front-End auf eine Anfrage zum Erstellen eines neuen Passkeys reagieren.

Funktionserkennung

Bevor Sie die Schaltfläche „Neuen Passkey erstellen“ anzeigen, prüfen Sie Folgendes:

  • Der Browser unterstützt WebAuthn.
  • Das Gerät unterstützt einen Plattform-Authenticator (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 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, solltest du vom Back-End wichtige Informationen zum Aufrufen von navigator.credentials.create() abrufen:

  • challenge: Eine vom Server generierte Aufgabe in ArrayBuffer für diese Registrierung. Dies ist erforderlich, wird aber während der Registrierung nicht verwendet, es sei denn, Sie führen die Attestierung aus. Dieses Thema für Fortgeschrittene wird hier nicht behandelt.
  • 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, ist gut geeignet.
  • 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. Dieser wird in der Kontoauswahl angezeigt. (Wenn Sie einen Nutzernamen verwenden, verwenden Sie denselben Wert wie bei der Passwortauthentifizierung.)
  • user.displayName: Dies ist ein erforderlicher, nutzerfreundlicherer Name für das Konto. Er muss nicht eindeutig sein und könnte der vom Nutzer gewählte Name sein. Wenn es auf Ihrer Website keinen geeigneten Wert gibt, den Sie hier einfügen können, übergeben Sie einen leeren String. Je nach Browser kann er in der Kontoauswahl angezeigt werden.
  • excludeCredentials: Verhindert die Registrierung desselben Geräts, indem eine Liste bereits registrierter Anmeldedaten-IDs zur Verfügung gestellt wird. Das Mitglied transports, falls angegeben, sollte 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 Promise zurück und wartet auf die Interaktion des Nutzers mit einem modalen Dialogfeld.

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 eine Website kann entweder ihre Domain oder ein registrierfähiges 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 mit login.example.com oder einer beliebigen Subdomain in example.com authentifizieren.

  • rp.name: Der Name der RP.

  • pubKeyCredParams: Dieses Feld gibt die unterstützten Public-Key-Algorithmen des RP an. Wir empfehlen, sie auf [{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}] festzulegen. Hiermit wird die Unterstützung von ECDSA mit P-256 und RSA PKCS#1 angegeben. Die Unterstützung dieser beiden Typen stellt eine vollständige Abdeckung dar.

  • authenticatorSelection.authenticatorAttachment: Setze diesen Wert auf "platform", wenn die Erstellung eines Passkeys ein Upgrade von einem Passwort ist, z.B. im Rahmen einer Werbeaktion nach einer Anmeldung. "platform" gibt an, dass die RP einen Plattform-Authenticator (einen in das Plattformgerät eingebetteten Authenticator) benötigt, der nicht auffordert, z.B. einen USB-Sicherheitsschlüssel einzufügen. Der Nutzer hat eine einfachere Option zum Erstellen eines Passkeys.

  • authenticatorSelection.requireResidentKey: Legen Sie den booleschen Wert „true“ fest. Mit auffindbaren Anmeldedaten (residenter Schlüssel) werden Nutzerinformationen im Passkey gespeichert. Nutzer können das Konto nach der Authentifizierung auswählen.

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

Zurückgegebene Anmeldedaten mit öffentlichem Schlüssel an Back-End senden

Nachdem der Nutzer seine Einwilligung zur Verwendung der Displaysperre des Geräts erteilt hat, wird ein Passkey erstellt und das Promise aufgelöst. Es wird ein PublicKeyCredential-Objekt an das Front-End zurückgegeben.

Das Versprechen kann aus verschiedenen Gründen abgelehnt werden. Zur Behebung dieser Fehler müssen 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.
  • NotAllowedError: Der Nutzer hat den Vorgang abgebrochen.
  • Andere Ausnahmen: Ein unerwarteter Fehler ist aufgetreten. Im Browser wird dem Nutzer ein Fehlerdialogfeld angezeigt.

Das Anmeldedatenobjekt für den öffentlichen Schlüssel enthält die folgenden Attribute:

  • id: Eine Base64URL-codierte ID des erstellten Passkeys. Anhand dieser ID kann der Browser feststellen, ob sich bei der Authentifizierung ein übereinstimmender Passkey im Gerät befindet. Dieser Wert muss in der Datenbank im Back-End gespeichert werden.
  • rawId: Eine ArrayBuffer-Version der Anmeldedaten-ID.
  • response.clientDataJSON: Ein ArrayBuffer-codierte Kundendaten.
  • response.attestationObject: Ein ArrayBuffer-codiertes Attestierungsobjekt. Es 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 verwenden, um das Anmeldedatenobjekt mit öffentlichem Schlüssel im Back-End zu verarbeiten, empfiehlt es sich, das gesamte Objekt nach der teilweisen Codierung mit base64url an das Back-End zu senden.

Anmeldedaten speichern

Nach Empfang der Anmeldedaten mit öffentlichem Schlüssel im Back-End übergeben Sie diese an die FIDO-Bibliothek, um das Objekt zu verarbeiten.

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

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

Die Anmeldedaten mit öffentlichem Schlüssel enthalten außerdem die folgenden Informationen, die Sie in der Datenbank speichern möchten:

Informationen zur Authentifizierung des Nutzers finden Sie unter Mit einem Passkey über das Autofill für Formulare anmelden.

Weitere Informationen