Details zu erkennbaren Anmeldedaten

FIDO-Anmeldedaten wie Passkeys sollen Passwörter ersetzen, aber die meisten davon können Nutzer auch von der Eingabe eines Nutzernamens befreien. Damit können sich Nutzer authentifizieren, indem sie ein Konto aus einer Liste von Passkeys für die aktuelle Website auswählen.

Frühere Versionen von Sicherheitsschlüsseln wurden als Methoden für die Bestätigung in zwei Schritten entwickelt und erforderten die IDs potenzieller Anmeldedaten, also die Eingabe eines Nutzernamens. Anmeldedaten, die ein Sicherheitsschlüssel finden kann, ohne ihre IDs zu kennen, werden als „findbare 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 als Passkeys (sichtbare Anmeldedaten) erstellt werden, geben Sie residentKey und requireResidentKey an, wenn die Anmeldedaten erstellt werden.

Vertrauende Parteien (Relying Partys, RPs) können auffindbare Anmeldedaten verwenden, indem sie allowCredentials während der Passkey-Authentifizierung. In diesen Fällen zeigt der Browser oder das System dem Nutzer eine Liste der verfügbaren Passkeys an, die durch das user.name-Property wurde bei der Erstellung festgelegt. Wenn der Nutzer eine Option auswählt, wird die user.id wird in die sich ergebende Signatur eingefügt. Der Server kann dann dieses oder Die zurückgegebene Anmeldedaten-ID, um das Konto anstelle eines eingegebenen Nutzernamens zu suchen.

Auf Benutzeroberflächen für die Kontoauswahl, wie die bereits erwähnten, werden niemals nicht sichtbare Anmeldedaten.

requireResidentKey und residentKey

Wenn Sie einen Passkey erstellen möchten, geben Sie authenticatorSelection.residentKey und authenticatorSelection.requireResidentKey unter 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 müssen Anmeldedaten erstellt werden, die gefunden werden können. Kann die Datei nicht erstellt werden, wird NotSupportedError zurückgegeben.
  • 'preferred': Die RP bevorzugt die Erstellung erkennbarer Anmeldedaten, akzeptiert aber nicht auffindbare Anmeldedaten.
  • 'discouraged': Der RP bevorzugt die Erstellung nicht auffindbarer Anmeldedaten, akzeptiert aber auch solche, die auffindbar sind.

requireResidentKey:

  • Diese Eigenschaft wird aus Gründen der Abwärtskompatibilität aus WebAuthn Level 1 übernommen, einer älteren Version der Spezifikation. Legen Sie diesen Wert auf true fest, wenn residentKey gleich 'required' ist, andernfalls 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:

Wenn Anmeldedaten sichtbar sind, wird in RPs eine modale Kontoauswahl angezeigt, über die der Nutzer ein Konto für die Anmeldung auswählen kann, gefolgt von der Nutzerbestätigung. Dies eignet sich für den Passkey-Authentifizierungsablauf, der durch Drücken einer Schaltfläche für die Passkey-Authentifizierung gestartet wird.

Für diese Funktion müssen Sie in navigator.credentials.get() ein leeres Array auslassen oder an den Parameter allowCredentials ü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 diese auf dem lokalen Gerät verfügbar sind. Wenn ein Nutzer keine lokalen Passkeys hat, wird das modale Dialogfeld trotzdem angezeigt und der Nutzer wird aufgefordert, einen Passkey von einem anderen Gerät vorzulegen. Bei der Umstellung Ihrer Nutzer auf Passkeys sollten Sie diese UI für Nutzer vermeiden, die noch keinen Passkeys eingerichtet haben.

Stattdessen kann die Auswahl eines Passkeys neben den gespeicherten Nutzernamen und Passwörtern in Autofill-Prompts für die Felder eines herkömmlichen Anmeldeformulars integriert werden. So kann ein Nutzer mit Passkeys im Anmeldeformular, indem sie ihren Passkey auswählen. Nutzer mit gespeicherten Nutzernamen/Passwort-Paaren können diese auswählen und Nutzer, die keines von beiden haben, können weiterhin ihren Nutzernamen und ihr Passwort eingeben.

Diese Nutzererfahrung ist ideal, wenn die RP sich in einer Migration befindet und Passwörter und Passkeys gemeinsam verwendet werden.

Dazu 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 UI angezeigt. Wenn der Nutzer jedoch den Fokus auf das Feld mit Anmerkungen legt, werden alle verfügbaren Passkeys in den Autofill-Optionen berücksichtigt. Wenn der Nutzer eine auswählt, wird die normale Bestätigung der Geräteentsperrung durchgeführt. Erst dann wird das von .get() zurückgegebene Versprechen mit einem Ergebnis aufgelöst. Wenn der Nutzer keinen Passkey auswählt, wird das Versprechen 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" ...>

Weitere Informationen dazu, wie Sie diese Nutzererfahrung gestalten, finden Sie unter Über die Formularautofill mit einem Passkey anmelden sowie im Codelab Passkeys mit Formularautofill in einer Webanwendung implementieren.

Erneute Authentifizierung

In einigen Fällen, z. B. wenn Passkeys zur erneuten Authentifizierung verwendet werden, ist die ID des Nutzers bereits bekannt. In diesem Fall möchten wir einen Passkey verwenden, ohne dass im Browser oder Betriebssystem eine Kontoauswahl angezeigt wird. Dazu wird eine Liste von Ausweisdokument-IDs im Parameter allowCredentials übergeben.

Wenn in diesem Fall eine der angegebenen Anmeldedaten lokal verfügbar ist, wird der Nutzer sofort zum Entsperren des Geräts aufgefordert. Andernfalls wird der Nutzer aufgefordert, ein anderes Gerät (ein Smartphone oder einen Sicherheitsschlüssel) vorzulegen, auf dem gültige Anmeldedaten gespeichert sind.

Geben Sie dazu eine Liste mit Anmeldedaten-IDs für den Nutzer an, der sich anmeldet. 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 mit öffentlichem Schlüssel, die der RP bei der Registrierung des Passkeys erhalten hat.
  • type: Dieses Feld enthält normalerweise 'public-key'.
  • transports: Ein Hinweis auf die Übertragungsmethoden, die vom Gerät mit diesen Anmeldedaten unterstützt werden. Wird von Browsern verwendet, um die Benutzeroberfläche zu optimieren, auf der der Nutzer aufgefordert wird, ein externes Gerät vorzulegen. Diese Liste sollte, sofern angegeben, das Ergebnis des Aufrufs von getTransports() während der Registrierung der einzelnen Anmeldedaten enthalten.

Zusammenfassung

Durch Anmeldedaten, die für andere sichtbar sind, wird die Anmeldung mit Passkeys viel nutzerfreundlicher, da die Eingabe eines Nutzernamens übersprungen werden kann. Mit der Kombination aus residentKey, requireResidentKey und allowCredentials können RPs Anmeldevorgänge ermöglichen, die:

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

Verwenden Sie auffindbare Anmeldedaten mit Bedacht. So können Sie eine ausgefeilte Passkey-Anmeldung entwerfen, die für Nutzer nahtlos ist und mit der sie eher interagieren.