Details zu erkennbaren Anmeldedaten

FIDO-Anmeldedaten wie Passkeys sollen Passwörter ersetzen. In den meisten Fällen kann der Nutzer damit auch auf die Eingabe eines Nutzernamens verzichten. So können sich Nutzer authentifizieren, indem sie ein Konto aus einer Liste von Passkeys auswählen, die sie für die aktuelle Website haben.

Frühere Versionen von Sicherheitsschlüsseln waren als Methoden zur 2‑Faktor-Authentifizierung konzipiert und erforderten die IDs potenzieller Anmeldedaten, sodass ein Nutzername eingegeben werden musste. Anmeldedaten, die ein Sicherheitsschlüssel ohne Kenntnis ihrer IDs finden kann, werden als auffindbare Anmeldedaten bezeichnet. Die meisten FIDO-Anmeldedaten, die heute erstellt werden, sind ermittelbare Anmeldedaten, insbesondere Passkeys, die in einem Passwortmanager oder auf einem modernen Sicherheitsschlüssel gespeichert sind.

Damit Ihre Anmeldedaten als Passkeys (auffindbare Anmeldedaten) erstellt werden, geben Sie beim Erstellen der Anmeldedaten residentKey und requireResidentKey an.

Vertrauende Parteien können auffindbare Anmeldedaten verwenden, indem sie allowCredentials während der Passkey-Authentifizierung weglassen. In diesen Fällen wird dem Nutzer im Browser oder System eine Liste der verfügbaren Passkeys angezeigt, die durch die beim Erstellen festgelegte user.name-Property identifiziert werden. Wenn der Nutzer eine Option 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.

In Benutzeroberflächen zur Kontoauswahl, wie den oben beschriebenen, werden nie nicht auffindbare Anmeldedaten angezeigt.

requireResidentKey und residentKey

Geben Sie zum Erstellen eines Passkeys authenticatorSelection.residentKey und authenticatorSelection.requireResidentKey für navigator.credentials.create() mit den folgenden Werten 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 auffindbares Anmeldedatenpaar erstellt werden. Wenn sie nicht erstellt werden kann, wird NotSupportedError zurückgegeben.
  • 'preferred': Der RP bevorzugt die Erstellung einer auffindbaren Anmeldedaten, akzeptiert aber auch nicht auffindbare Anmeldedaten.
  • 'discouraged': Der RP bevorzugt die Erstellung von Anmeldedaten ohne offenen Zugang, akzeptiert aber Anmeldedaten mit offenem Zugang.

requireResidentKey:

  • Diese Eigenschaft wird aus Gründen der Abwärtskompatibilität mit 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. In der Regel gibt es drei Arten der Passkey-Authentifizierung:

Mit auffindbaren Anmeldedaten können RPs eine modale Kontoauswahl für den Nutzer anzeigen, damit er ein Konto für die Anmeldung auswählen kann. Anschließend erfolgt die Nutzerbestätigung. Dies eignet sich für den Passkey-Authentifizierungsablauf, der durch Drücken einer Schaltfläche für die Passkey-Authentifizierung initiiert wird.

Um diese User Experience zu erzielen, lassen Sie den Parameter allowCredentials in navigator.credentials.get() weg oder übergeben Sie ein leeres Array.

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;
  
  // ...
}

Autofill-Vorgang für ein Passkey-Formular anzeigen

Die oben beschriebene modale Kontoauswahl funktioniert gut, wenn die meisten Nutzer Passkeys verwenden und diese auf dem lokalen Gerät verfügbar sind. Bei Nutzern, die keine lokalen Passkeys haben, wird das modale Dialogfeld weiterhin angezeigt und sie werden aufgefordert, einen Passkey von einem anderen Gerät zu präsentieren. Während Sie Ihre Nutzer auf Passkeys umstellen, möchten Sie möglicherweise vermeiden, dass die Benutzeroberfläche für Nutzer angezeigt wird, die noch keinen Passkey eingerichtet haben.

Stattdessen kann die Auswahl eines Passkeys in die Aufforderungen zum automatischen Ausfüllen für die Felder in einem herkömmlichen Anmeldeformular zusammen mit gespeicherten Nutzernamen und Passwörtern integriert werden. So kann ein Nutzer mit Passkeys das Anmeldeformular „ausfüllen“, indem er seinen Passkey auswählt. Nutzer mit gespeicherten Nutzername/Passwort-Paaren können diese auswählen und Nutzer ohne beides können weiterhin ihren Nutzernamen und ihr Passwort eingeben.

Diese Nutzerfreundlichkeit ist ideal, wenn der RP migriert wird und Passwörter und Passkeys gemischt verwendet werden.

Um diese Nutzerfreundlichkeit zu erreichen, müssen Sie nicht nur ein leeres Array an die Property allowCredentials übergeben oder den Parameter weglassen, sondern auch mediation: 'conditional' für navigator.credentials.get() angeben und ein HTML-username-Eingabefeld mit autocomplete="username webauthn" oder ein password-Eingabefeld mit autocomplete="password webauthn" annotieren.

Durch den Aufruf von navigator.credentials.get() wird keine Benutzeroberfläche angezeigt. Wenn der Nutzer jedoch das annotierte Eingabefeld fokussiert, werden alle verfügbaren Passkeys in die Optionen für das automatische Ausfüllen aufgenommen. Wenn der Nutzer eine Option auswählt, wird die reguläre Geräteentsperrungsüberprüfung durchgeführt. Erst dann wird das von .get() zurückgegebene Promise mit einem Ergebnis aufgelöst. Wenn der Nutzer keinen Passkey auswählt, wird das Promise nie 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 zum Erstellen dieser Nutzererfahrung finden Sie unter Mit einem Passkey über das Autofill-Formular anmelden sowie im Codelab Passkeys mit dem Autofill-Formular in einer Web-App implementieren.

Erneute Authentifizierung

In einigen Fällen, z. B. bei der Verwendung von Passkeys für die erneute Authentifizierung, ist die Kennung des Nutzers bereits bekannt. In diesem Fall möchten wir einen Passkey verwenden, ohne dass im Browser oder Betriebssystem eine Kontoauswahl angezeigt wird. Dazu übergeben Sie eine Liste von Anmeldedaten-IDs im Parameter allowCredentials.

Wenn in diesem Fall eine der genannten Anmeldedaten lokal verfügbar ist, wird der Nutzer sofort aufgefordert, das Gerät zu entsperren. Andernfalls wird der Nutzer aufgefordert, ein anderes Gerät (ein Smartphone oder einen Sicherheitsschlüssel) mit gültigen Anmeldedaten zu präsentieren.

Um diese Nutzerfreundlichkeit zu erreichen, müssen Sie eine Liste der Berechtigungsnachweis-IDs für den angemeldeten Nutzer bereitstellen. Der RP sollte sie abfragen können, da der Nutzer bereits bekannt ist. Geben Sie Anmeldedaten-IDs als PublicKeyCredentialDescriptor-Objekte in der Property 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 für den öffentlichen Schlüssel, die der RP bei der Passkey-Registrierung erhalten hat.
  • type: Dieses Feld ist in der Regel 'public-key'.
  • transports: Ein Hinweis auf die vom Gerät mit diesem Anmeldedaten unterstützten Transportmethoden, der von Browsern verwendet wird, um die Benutzeroberfläche zu optimieren, in der der Nutzer aufgefordert wird, ein externes Gerät zu präsentieren. Diese Liste sollte, sofern angegeben, das Ergebnis des Aufrufs von getTransports() während der Registrierung der einzelnen Anmeldedaten enthalten.

Zusammenfassung

Durch auffindbare Anmeldedaten wird die Anmeldung mit Passkeys viel nutzerfreundlicher, da Nutzer keinen Nutzernamen mehr eingeben müssen. Durch die Kombination von residentKey, requireResidentKey und allowCredentials können RPs Anmeldevorgänge anbieten, die:

  • Eine modale Kontoauswahl anzeigen.
  • Autofill-Vorgang für ein Passkey-Formular anzeigen
  • Erneute Authentifizierung.

Verwenden Sie auffindbare Anmeldedaten mit Bedacht. So können Sie ausgefeilte Passkey-Anmeldungen entwickeln, die für Nutzer nahtlos funktionieren und mit denen sie eher interagieren.