Im Detail erkennbare Anmeldedaten

FIDO-Anmeldedaten wie Passkeys zielen darauf ab, Passwörter zu ersetzen. Mit den meisten davon müssen Nutzer außerdem keinen Nutzernamen mehr eingeben. Nutzer können sich dadurch authentifizieren, indem sie ein Konto aus einer Liste von Passkeys für die aktuelle Website auswählen.

Frühere Versionen von Sicherheitsschlüsseln wurden für die Bestätigung in zwei Schritten entwickelt und erforderten die IDs potenzieller Anmeldedaten, weshalb die Eingabe eines Nutzernamens erforderlich war. Anmeldedaten, die ein Sicherheitsschlüssel finden kann, ohne dass die IDs bekannt sind, werden als auffindbare Anmeldedaten bezeichnet. Die meisten heute erstellten FIDO-Anmeldedaten sind auffindbare Anmeldedaten, insbesondere Passkeys, die in einem Passwortmanager oder auf einem modernen Sicherheitsschlüssel gespeichert sind.

Damit Ihre Anmeldedaten auffindbar sind, geben Sie beim Erstellen des Passkeys residentKey und requireResidentKey an.

Vertrauende Parteien (RPs) können auffindbare Anmeldedaten verwenden, indem sie allowCredentials bei der Passkey-Authentifizierung weglassen. In diesen Fällen zeigt der Browser oder das System dem Nutzer eine Liste der verfügbaren Passkeys an, die durch das Attribut user.name identifiziert werden, das bei der Erstellung festgelegt wurde. Wenn der Nutzer eine auswählt, wird der user.id-Wert in die resultierende Signatur aufgenommen. Der Server kann dann diese oder die zurückgegebene Anmeldedaten-ID verwenden, um das Konto anstelle eines eingegebenen Nutzernamens zu suchen.

Auf Benutzeroberflächen für die Kontoauswahl, wie oben beschrieben, werden keine Anmeldedaten angezeigt, die nicht sichtbar sind.

requireResidentKey und residentKey

Wenn Sie Anmeldedaten mit offenem Zugang erstellen möchten, geben Sie im navigator.credentials.create() mit den folgenden Werten authenticatorSelection.residentKey und authenticatorSelection.requireResidentKey an.

async function register () {
  // ...

  const publicKeyCredentialCreationOptions = {
    // ...
    authenticatorSelection: {
      authenticatorAttachment: 'platform',
      residentKey: 'required',
      requireResidentKey: true,
    }
  };

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

  // This does not run until the user selects a passkey.
  const credential = {};
  credential.id = cred.id;
  credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
  credential.type = cred.type;

  // ...
}

residentKey:

  • 'required': Es muss ein sichtbarer Berechtigungsnachweis erstellt werden. Wenn sie nicht erstellt werden kann, wird NotSupportedError zurückgegeben.
  • 'preferred': Das RP bevorzugt einen erkennbaren Berechtigungsnachweis, akzeptiert aber einen nicht auffindbaren Berechtigungsnachweis.
  • 'discouraged': Das RP bevorzugt vorzugsweise Anmeldedaten, die nicht sichtbar sind, akzeptiert aber Anmeldedaten.

requireResidentKey:

  • Diese Eigenschaft wird aus Gründen der Abwärtskompatibilität von WebAuthn Level 1, einer älteren Version der Spezifikation, beibehalten. Setzen Sie diesen Wert auf true, wenn residentKey gleich 'required' ist. Andernfalls setzen Sie ihn auf false.

allowCredentials

RPs können allowCredentials auf navigator.credentials.get() verwenden, um die Passkey-Authentifizierung zu steuern. Üblicherweise gibt es drei Arten von Passkey-Authentifizierungsmethoden:

Mit sichtbaren Anmeldedaten können RPs eine modale Kontoauswahl anzeigen, über die der Nutzer ein Konto für die Anmeldung auswählen kann, gefolgt von einer Nutzerbestätigung. Diese Option eignet sich für einen Passkey-Authentifizierungsvorgang, der durch Drücken einer Schaltfläche für die Passkey-Authentifizierung initiiert wird.

Um dies zu erreichen, sollten Sie ein leeres Array weglassen oder an den allowCredentials-Parameter in navigator.credentials.get() übergeben.

async function authenticate() {
  // ...

  const publicKeyCredentialRequestOptions = {
    // Server generated challenge:
    challenge: ****,
    // The same RP ID as used during registration:
    rpId: 'example.com',
    // You can omit `allowCredentials` as well:
    allowCredentials: []
  };

  const credential = await navigator.credentials.get({
    publicKey: publicKeyCredentialRequestOptions,
    signal: abortController.signal
  });

  // This does not run until the user selects a passkey.
  const credential = {};
  credential.id = cred.id;
  credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
  credential.type = cred.type;
  
  // ...
}

Passkey-Formular automatisch ausfüllen lassen

Die oben beschriebene modale Kontoauswahl funktioniert gut, wenn die meisten Nutzer Passkeys verwenden und auf dem lokalen Gerät verfügbar sind. Wenn ein Nutzer keine lokalen Passkeys hat, wird das modale Dialogfeld trotzdem angezeigt, in dem er einen Passkey von einem anderen Gerät vorzeigen kann. Bei der Umstellung Ihrer Nutzer auf Passkeys sollten Sie diese Benutzeroberfläche bei Nutzern vermeiden, die keine Passkeys eingerichtet haben.

Stattdessen kann die Auswahl eines Passkeys neben gespeicherten Nutzernamen und Passwörtern in Autofill-Aufforderungen für die Felder in einem herkömmlichen Anmeldeformular zusammengefasst werden. Auf diese Weise können Nutzer mit Passkeys das Anmeldeformular ausfüllen, indem sie ihren Passkey auswählen. Nutzer mit gespeicherten Paaren aus Nutzername und Passwort können diese auswählen und Nutzer, die weder den Nutzernamen noch das Passwort eingeben, können diese manuell eingeben.

Diese Nutzererfahrung ist ideal, wenn das RP eine Migration mit einer gemischten Verwendung von Passwörtern und Passkeys durchführt.

Für die Nutzerfreundlichkeit sollten Sie zusätzlich zur Übergabe eines leeren Arrays an die Eigenschaft allowCredentials oder beim Weglassen des Parameters mediation: 'conditional' für navigator.credentials.get() angeben und ein HTML-Eingabefeld vom Typ username mit autocomplete="username webauthn" oder einem password-Eingabefeld mit autocomplete="password webauthn" annotieren.

Durch den Aufruf von navigator.credentials.get() wird keine UI angezeigt. Wenn der Nutzer jedoch das mit Anmerkungen versehene Eingabefeld auswählt, werden alle verfügbaren Passkeys in die Autofill-Optionen aufgenommen. Wenn der Nutzer eine Option auswählt, durchläuft er die normale Bestätigung der Entsperrung des Geräts. Erst dann wird das von .get() zurückgegebene Promise mit einem Ergebnis aufgelöst. Wenn der Nutzer keinen Passkey auswählt, wird das Versprechen niemals aufgelöst.

async function authenticate() {
  // ...

  const publicKeyCredentialRequestOptions = {
    // Server generated challenge:
    challenge: ****,
    // The same RP ID as used during registration:
    rpId: 'example.com',
    // You can omit `allowCredentials` as well:
    allowCredentials: []
  };

  const cred = await navigator.credentials.get({
    publicKey: publicKeyCredentialRequestOptions,
    signal: abortController.signal,
    // Specify 'conditional' to activate conditional UI
    mediation: 'conditional'
  });

  // This does not run until the user selects a passkey.
  const credential = {};
  credential.id = cred.id;
  credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
  credential.type = cred.type;
  
  // ...
}
<input type="text" name="username" autocomplete="username webauthn" ...>

Informationen dazu, wie Sie diese Nutzererfahrung verbessern können, finden Sie unter Mit einem Passkey über Autofill für Formulare anmelden und im Codelab Passkeys mit Autofill für Formulare in einer Web-App implementieren.

Erneute Authentifizierung

In einigen Fällen, z. B. wenn Passkeys für die erneute Authentifizierung verwendet werden, ist die ID des Nutzers bereits bekannt. In diesem Fall würden wir einen Passkey verwenden, ohne dass im Browser oder Betriebssystem eine Kontoauswahl angezeigt wird. Dazu muss im Parameter allowCredentials eine Liste von Anmeldedaten-IDs übergeben werden.

Wenn eine der benannten Anmeldedaten lokal verfügbar ist, wird der Nutzer sofort aufgefordert, das Gerät zu entsperren. Ist dies nicht der Fall, wird der Nutzer aufgefordert, ein anderes Gerät (Smartphone oder Sicherheitsschlüssel) mit gültigen Anmeldedaten vorzuzeigen.

Stellen Sie eine Liste mit Anmeldedaten-IDs für den anmeldenden Nutzer bereit, um dies zu ermöglichen. Die RP sollte sie abfragen können, da der Nutzer bereits bekannt ist. Gib Anmeldedaten-IDs als PublicKeyCredentialDescriptor-Objekte im Attribut allowCredentials in navigator.credentials.get() an.

async function authenticate() {
  // ...

  const publicKeyCredentialRequestOptions = {
    // Server generated challenge:
    challenge: ****,
    // The same RP ID as used during registration:
    rpId: 'example.com',
    // Provide a list of PublicKeyCredentialDescriptors:
    allowCredentials: [{
      id: ****,
      type: 'public-key',
      transports: [
        'internal',
        'hybrid'
      ]
    }, {
      id: ****,
      type: 'public-key',
      transports: [
        'internal',
        'hybrid'
      ]
    }, ...]
  };

  const credential = await navigator.credentials.get({
    publicKey: publicKeyCredentialRequestOptions,
    signal: abortController.signal
  });

  // This does not run until the user selects a passkey.
  const credential = {};
  credential.id = cred.id;
  credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
  credential.type = cred.type;
  
  // ...
}

Ein PublicKeyCredentialDescriptor-Objekt besteht aus:

  • id: Eine ID der Anmeldedaten mit öffentlichem Schlüssel, die der RP für die Passkey-Registrierung erhalten hat.
  • type: Dieses Feld ist normalerweise 'public-key'.
  • transports: Ein Hinweis zu Transporten, die vom Gerät mit diesen Anmeldedaten unterstützt werden und von Browsern zur Optimierung der Benutzeroberfläche verwendet wird, über die der Nutzer aufgefordert wird, ein externes Gerät zu präsentieren. Sofern vorhanden, sollte diese Liste das Ergebnis des Aufrufs von getTransports() während der Registrierung des jeweiligen Berechtigungsnachweises enthalten.

Zusammenfassung

Durch erkennbare Anmeldedaten wird die Passkey-Anmeldung viel nutzerfreundlicher, da die Eingabe des Nutzernamens übersprungen werden kann. Mit der Kombination von residentKey, requireResidentKey und allowCredentials können RPs bei der Anmeldung Folgendes erreichen:

  • Modale Kontoauswahl einblenden.
  • Passkey-Formular automatisch ausfüllen lassen.
  • Erneute Authentifizierung.

Verwenden Sie auffindbare Anmeldedaten mit Bedacht. So können Sie eine ausgefeilte Passkey-Anmeldung entwickeln, die eine reibungslose Anmeldung ermöglicht und mit größerer Wahrscheinlichkeit verwendet wird.