Details zu erkennbaren Anmeldedaten

FIDO-Anmeldedaten wie Passkeys sollen Passwörter ersetzen. Die meisten von ihnen können Nutzer aber auch davon befreien, einen Nutzernamen einzugeben. 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 wurden als Authentifizierungsmethoden zur 2‑Faktor-Authentifizierung entwickelt und erforderten die IDs potenzieller Anmeldedaten, sodass ein Nutzername eingegeben werden musste. Anmeldedaten, die ein Sicherheitsschlüssel finden kann, ohne ihre IDs zu kennen, 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 als Passkeys (auffindbare Anmeldedaten) erstellt werden, geben Sie beim Erstellen der Anmeldedaten residentKey und requireResidentKey an.

Relying Parties (RPs) können auffindbare Anmeldedaten verwenden, indem sie bei der Passkey-Authentifizierung allowCredentials weglassen. In diesen Fällen zeigt der Browser oder das System dem Nutzer eine Liste der verfügbaren Passkeys an, die durch das bei der Erstellung festgelegte Attribut user.name identifiziert werden. Wenn der Nutzer einen 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 zu suchen, anstatt einen eingegebenen Nutzernamen zu verwenden.

In Benutzeroberflächen für die Kontoauswahl, wie sie oben beschrieben wurden, werden niemals nicht auffindbare Anmeldedaten angezeigt.

requireResidentKey und residentKey

Wenn Sie einen Passkey erstellen möchten, geben Sie 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 müssen auffindbare Anmeldedaten erstellt werden. Wenn sie nicht erstellt werden kann, wird NotSupportedError zurückgegeben.
  • 'preferred': Die vertrauende Seite bevorzugt die Erstellung von auffindbaren Anmeldedaten, akzeptiert aber auch nicht auffindbare Anmeldedaten.
  • 'discouraged': Die vertrauende Seite bevorzugt die Erstellung von nicht auffindbaren Anmeldedaten, akzeptiert aber auch auffindbare Anmeldedaten.

requireResidentKey:

  • Diese Property wird aus Gründen der Abwärtskompatibilität mit WebAuthn Level 1, einer älteren Version der Spezifikation, beibehalten. Legen Sie hierfür true fest, wenn residentKey gleich 'required' ist. Andernfalls legen Sie false fest.

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 vertrauende Seiten eine modale Kontoauswahl anzeigen, über die der Nutzer 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 Taste für die Passkey-Authentifizierung gestartet wird.

Dazu müssen Sie den Parameter allowCredentials in navigator.credentials.get() weglassen oder ein leeres Array ü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;
  
  // ...
}

Autofill-Formular für Passkeys anzeigen

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

Stattdessen kann die Auswahl eines Passkeys in die Aufforderungen zum automatischen Ausfüllen der Felder in einem herkömmlichen Anmeldeformular eingebunden werden, zusammen mit gespeicherten Nutzernamen und Passwörtern. So können Nutzer mit Passkeys das Anmeldeformular durch Auswahl ihres Passkeys „ausfüllen“, Nutzer mit gespeicherten Nutzernamen/Passwort-Kombinationen können diese auswählen und Nutzer ohne beides können weiterhin ihren Nutzernamen und ihr Passwort eingeben.

Diese Nutzererfahrung ist ideal, wenn die RP sich in einer Migrationsphase befindet und sowohl Passwörter als auch Passkeys verwendet werden.

Um diese Nutzererfahrung 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.

Der Aufruf von navigator.credentials.get() führt nicht dazu, dass eine Benutzeroberfläche angezeigt wird. Wenn der Nutzer jedoch das annotierte Eingabefeld fokussiert, werden alle verfügbaren Passkeys in die Autofill-Optionen aufgenommen. Wenn der Nutzer eine Option auswählt, wird er durch die reguläre Bestätigung zum Entsperren des Geräts gefü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=&qu>ot;username webauthn" ...

Informationen zum Erstellen dieser Nutzererfahrung finden Sie unter Mit einem Passkey über das automatische Ausfüllen von Formularen anmelden und im Codelab Passkeys mit automatischem Ausfüllen von Formularen 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 der Browser oder das Betriebssystem eine Kontoauswahl anzeigt. Dazu können Sie eine Liste von Anmeldedaten-IDs im Parameter allowCredentials übergeben.

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 vorzulegen.

Um diese Nutzererfahrung zu ermöglichen, stellen Sie eine Liste der Anmeldedaten-IDs für den sich anmeldenden Nutzer bereit. Die RP sollte sie abfragen können, da der Nutzer bereits bekannt ist. Geben Sie die Ausweis-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 für den öffentlichen Schlüssel, die die vertrauende Seite bei der Passkey-Registrierung erhalten hat.
  • type: Dieses Feld ist normalerweise 'public-key'.
  • transports: Ein Hinweis auf die vom Gerät, das diese Anmeldedaten enthält, unterstützten Übertragungsarten. Er wird von Browsern verwendet, um die Benutzeroberfläche zu optimieren, über die der Nutzer aufgefordert wird, ein externes Gerät zu präsentieren. Diese Liste sollte, falls angegeben, das Ergebnis des Aufrufs von getTransports() während der Registrierung der einzelnen Anmeldedaten enthalten.

Zusammenfassung

Auffindbare Anmeldedaten machen die Anmeldung mit Passkeys viel nutzerfreundlicher, da Nutzer keinen Nutzernamen eingeben müssen. Durch die Kombination von residentKey, requireResidentKey und allowCredentials können RPs Anmeldeverfahren anbieten, die:

  • Ein modales Fenster zur Kontoauswahl anzeigen.
  • Formular für automatisches Ausfüllen von Passkeys anzeigen.
  • Erneute Authentifizierung.

Verwenden Sie auffindbare Anmeldedaten mit Bedacht. So können Sie anspruchsvolle Passkey-Anmeldeverfahren entwickeln, die Nutzer als nahtlos empfinden und die sie eher nutzen.