Identitätslösung mit FedCM auf Identitätsanbieterseite implementieren

Die FedCM-Implementierung umfasst mehrere wichtige Schritte für Identitätsanbieter (IdP) und Anwendungen (Relying Party, RP). In der Dokumentation erfahren Sie, wie Sie FedCM auf der Seite des RP implementieren.

IdPs müssen die folgenden Schritte ausführen, um FedCM zu implementieren:

.well-known-Datei erstellen

Damit Tracker die API nicht missbrauchen, muss eine well-known-Datei von /.well-known/web-identity der eTLD+1 des IdP bereitgestellt werden.

Die Datei „well-known“ kann die folgenden Properties enthalten:

Attribut Erforderlich Beschreibung
provider_urls erforderlich Array von IdP-Konfigurationsdateipfaden. Wird ignoriert (ist aber weiterhin erforderlich), wenn accounts_endpoint und login_url angegeben sind.
accounts_endpoint Empfohlen, erfordert login_url
URL für den Kontenendpunkt. Dies ermöglicht die Unterstützung mehrerer Konfigurationen, sofern in jeder Konfigurationsdatei dieselbe login_url- und accounts_endpoint-URL verwendet wird.

Hinweis: Der Parameter wird ab Chrome 132 unterstützt.
login_url Empfohlen, erfordert accounts_endpoint Die URL der Anmeldeseite, über die sich der Nutzer beim IdP anmelden kann. Dadurch wird die Unterstützung mehrerer Konfigurationen ermöglicht, sofern in jeder Konfigurationsdatei dieselben login_url und accounts_endpoint verwendet werden.

Hinweis: Der Parameter wird ab Chrome 132 unterstützt.

Wenn die IdP-Endpunkte beispielsweise unter https://accounts.idp.example/ bereitgestellt werden, muss eine well-known-Datei unter https://idp.example/.well-known/web-identity sowie eine IdP-Konfigurationsdatei bereitgestellt werden. Hier sehen Sie ein Beispiel für den Inhalt einer well-known-Datei:

  {
    "provider_urls": ["https://accounts.idp.example/config.json"]
  }

Identitätsanbieter können mehrere Konfigurationsdateien für einen Identitätsanbieter unterstützen, indem sie accounts_endpoint und login_url in der bekannten Datei angeben. Diese Funktion kann in folgenden Fällen nützlich sein:

  • Ein IdP muss mehrere verschiedene Test- und Produktionskonfigurationen unterstützen.
  • Ein IdP muss verschiedene Konfigurationen pro Region unterstützen (z. B. eu-idp.example und us-idp.example).

Zur Unterstützung mehrerer Konfigurationen (z. B. zur Unterscheidung zwischen Test- und Produktionsumgebung) muss der IdP accounts_endpoint und login_url angeben:

  {
    // This property is required, but will be ignored when IdP supports
    // multiple configs (when `accounts_endpoint` and `login_url` are
    // specified), as long as `accounts_endpoint` and `login_url` in
    // that config file match those in the well-known file.
    "provider_urls": [ "https://idp.example/fedcm.json" ],

    // Specify accounts_endpoint and login_url properties to support
    // multiple config files.
    // Note: The accounts_endpoint and login_url must be identical
    // across all config files. Otherwise,
    // the configurations won't be supported.
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }

IdP-Konfigurationsdatei und Endpunkte erstellen

Die IdP-Konfigurationsdatei enthält eine Liste der erforderlichen Endpunkte für den Browser. IdPs müssen eine oder mehrere Konfigurationsdateien sowie die erforderlichen Endpunkte und URLs hosten. Alle JSON-Antworten müssen mit dem Content-Type application/json bereitgestellt werden.

Die URL der Konfigurationsdatei wird durch die Werte bestimmt, die für den navigator.credentials.get()-Aufruf angegeben werden, der auf einem RP ausgeführt wird. Der RP übergibt die URL der Konfigurationsdatei für jeden Identitätsanbieter:

  // Executed on RP's side:
  try {
    const credential = await navigator.credentials.get({
      identity: {
        providers: [
          {
            // To allow users to sign in with the IdP1 using FedCM, RP specifies the IdP's config file URL:
            configUrl: 'https://idp1.example/foo.json', // first IdP
            clientId: '123',
          },
          // To allow users to sign in with the IdP2 using FedCM, RP specifies the IdP's config file URL.
          // Note that multiple IdPs in a single get() are supported from Chrome 136.
          {
            configUrl: 'https://idp2.example/bar.json', // second IdP
            clientId: '456',
          },
        ],
      },
    });

    const token = credential.token;
    // Get the current IdP's configURL to identify which provider the user is signed in with
    const currentIdpConfigUrl = credential.configURL;
    if (currentIdpConfigUrl === 'https://idp1.example/foo.json') {
      // handle the case where the user signed in with idp1
    } else if (currentIdpConfigUrl === 'https://idp2.example/bar.json') {
      // handle the case where the user signed in with idp2
    }
  } catch (error) {
    // handle error
  }

Der Browser ruft die Konfigurationsdatei mit einer GET-Anfrage ohne den Origin-Header oder den Referer-Header ab. Die Anfrage enthält keine Cookies und folgt keinen Weiterleitungen. Dadurch wird verhindert, dass der Identitätsanbieter erfährt, wer die Anfrage gestellt hat und welcher RP versucht, eine Verbindung herzustellen. Beispiel:

  GET /config.json HTTP/1.1
  Host: accounts.idp.example
  Accept: application/json
  Sec-Fetch-Dest: webidentity

Der Identitätsanbieter muss einen Konfigurationsendpunkt implementieren, der mit einem JSON antwortet. Das JSON enthält die folgenden Eigenschaften:

Attribut Beschreibung
accounts_endpoint (erforderlich) URL für den accounts-Endpunkt.
account_label (optional) Benutzerdefinierter Kontolabelstring, der bestimmt, welche Konten zurückgegeben werden sollen, wenn diese Konfigurationsdatei verwendet wird, z. B. "account_label": "developer".
Ein IdP kann benutzerdefinierte Kontolabel so implementieren:
  • Erstellen Sie eine Konfigurationsdatei, die bestimmten Labels zugeordnet ist (mit dem Parameter account_label).
  • Geben Sie Labels im Kontenendpunkt an.

Ein IdP implementiert beispielsweise die "https://idp.example/developer-config.json"-Konfigurationsdatei mit der Angabe von "account_label": "developer". Der IdP kennzeichnet außerdem einige Konten mit dem Label "developer". Dazu wird der Parameter label_hints im accounts-Endpunkt verwendet. Wenn ein RP navigator.credentials.get() mit der angegebenen "https://idp.example/developer-config.json"-Konfigurationsdatei aufruft, werden nur Konten mit dem Label "developer" zurückgegeben.

Hinweis: Benutzerdefinierte Kontolabel werden ab Chrome 132 unterstützt.
supports_use_other_account (optional) Boolescher Wert, der angibt, ob sich der Nutzer mit einem anderen Konto als dem, mit dem er derzeit angemeldet ist, anmelden kann (wenn der Identitätsanbieter mehrere Konten unterstützt). Das gilt nur für den Aktivmodus.
client_metadata_endpoint (optional) URL für den Clientmetadaten-Endpunkt.
id_assertion_endpoint (erforderlich) URL für den ID-Assertion-Endpunkt.
disconnect (optional) URL für den Endpunkt zum Trennen der Verbindung.
login_url (erforderlich) Die URL der Anmeldeseite, über die sich der Nutzer beim IdP anmelden kann.
branding (optional) Objekt, das verschiedene Branding-Optionen enthält.
branding.background_color (optional) Branding-Option, mit der die Hintergrundfarbe der Schaltfläche „Weiter als…“ festgelegt wird. Verwenden Sie die entsprechende CSS-Syntax, nämlich hex-color, hsl(), rgb() oder named-color.
branding.color (optional) Branding-Option, mit der die Textfarbe der Schaltfläche „Weiter als…“ festgelegt wird. Verwenden Sie die entsprechende CSS-Syntax, nämlich hex-color, hsl(), rgb() oder named-color.
branding.icons (optional) Array von Symbolobjekten. Diese Symbole werden im Log-in-Dialogfeld angezeigt. Das Symbolobjekt hat zwei Parameter:
  • url (erforderlich): URL des Symbols. SVG-Bilder werden nicht unterstützt.
  • size (optional): Abmessungen des Symbols, das von der Anwendung als quadratisch und mit einer einzigen Auflösung angenommen wird. Diese Zahl muss im passiven Modus größer oder gleich 25 px und im aktiven Modus größer oder gleich 40 px sein.

Hier ist ein Beispiel für den Antworttext vom IdP:

  {
    "accounts_endpoint": "/accounts.example",
    "client_metadata_endpoint": "/client_metadata.example",
    "id_assertion_endpoint": "/assertion.example",
    "disconnect_endpoint": "/disconnect.example",
    "login_url": "/login",
    // When RPs use this config file, only those accounts will be
    //returned that include `developer` label in the accounts endpoint.
    "account_label": "developer",
    "supports_use_other_account": true,
    "branding": {
      "background_color": "green",
      "color": "#FFEEAA",
      "icons": [{
        "url": "https://idp.example/icon.ico",
        "size": 25
      }]
    }
  }

Sobald der Browser die Konfigurationsdatei abgerufen hat, werden nachfolgende Anfragen an die IdP-Endpunkte gesendet:

IdP-Endpunkte
IdP-Endpunkte

Anderes Konto verwenden

Nutzer können zu einem Konto wechseln, das sich von dem unterscheidet, mit dem sie derzeit angemeldet sind, wenn der IdP mehrere Konten unterstützt oder das vorhandene Konto ersetzt.

Damit der Nutzer andere Konten auswählen kann, muss der IdP diese Funktion in der Konfigurationsdatei angeben:

  {
    "accounts_endpoint" : "/accounts.example",
    "supports_use_other_account": true
  }

Kontenendpunkt

Der Kontenendpunkt des Identitätsanbieters gibt eine Liste der Konten zurück, in denen der Nutzer beim Identitätsanbieter angemeldet ist. Wenn der IdP mehrere Konten unterstützt, werden von diesem Endpunkt alle angemeldeten Konten zurückgegeben.

Der Browser sendet eine GET-Anfrage mit Cookies mit SameSite=None, aber ohne den Parameter client_id, den Header Origin oder den Header Referer. So wird effektiv verhindert, dass der IdP erfährt, bei welchem RP sich der Nutzer anmelden möchte. Beispiel:

  GET /accounts.example HTTP/1.1
  Host: accounts.idp.example
  Accept: application/json
  Cookie: 0x23223
  Sec-Fetch-Dest: webidentity

Nach Erhalt der Anfrage sollte der Server Folgendes tun:

  1. Prüfen Sie, ob die Anfrage einen Sec-Fetch-Dest: webidentity-HTTP-Header enthält.
  2. Die Sitzungscookies werden mit den IDs der bereits angemeldeten Konten abgeglichen.
  3. Antworte mit der Liste der Konten.

Der Browser erwartet eine JSON-Antwort mit dem Attribut accounts, das ein Array mit Kontoinformationen mit den folgenden Attributen enthält:

Attribut Beschreibung
id (erforderlich) Eindeutige ID des Nutzers.
name Vollständiger Name des Nutzers entsprechend seinem Gebietsschema und seinen Einstellungen.

Hinweis: Ab Chrome 141 ist mindestens einer der Parameter name, email, username oder tel erforderlich. In früheren Chrome-Versionen sind sowohl name als auch email erforderlich.
username Ein vom Nutzer gewählter Nutzername.

Hinweis: Ab Chrome 141 ist mindestens einer der Parameter name, email, username oder tel erforderlich.
email E-Mail-Adresse des Nutzers

Hinweis: Ab Chrome 141 ist mindestens einer der Parameter name, email, username oder tel erforderlich. In früheren Chrome-Versionen sind sowohl name als auch email erforderlich.
tel Telefonnummer des Nutzers

Hinweis: Ab Chrome 141 ist mindestens einer der Parameter name, email, username oder tel erforderlich.
picture (optional) URL des Nutzeravatarbilds.
given_name (optional) Vorname des Nutzers.
approved_clients (optional) Ein Array von RP-Client-IDs, mit denen sich der Nutzer registriert hat.
login_hints (optional) Ein Array aller möglichen Filtertypen, die der Identitätsanbieter unterstützt, um ein Konto anzugeben. Der RP kann navigator.credentials.get() mit der Property loginHint aufrufen, um das angegebene Konto selektiv anzuzeigen.
domain_hints (optional) Ein Array aller Domains, die dem Konto zugeordnet sind. Der RP kann navigator.credentials.get() mit einer domainHint-Property aufrufen, um die Konten zu filtern.
label_hints (optional) Array mit benutzerdefinierten Kontolabels, die einem Konto zugeordnet sind.
Ein IdP kann benutzerdefinierte Kontolabel so implementieren:
  • Geben Sie Kontolabel im Kontenendpunkt an (mit dem Parameter label_hints).
  • Erstellen Sie für jedes Label eine Konfigurationsdatei.

Ein IdP implementiert beispielsweise die https://idp.example/developer-config.json-Konfigurationsdatei mit der Angabe von "account_label": "developer". Der IdP kennzeichnet einige Konten auch mit dem Label "developer". Dazu wird der Parameter label_hints im Kontenendpunkt verwendet. Wenn ein RP navigator.credentials.get() mit einer angegebenen https://idp.example/developer-config.json-Konfigurationsdatei aufruft, werden nur Konten mit dem Label "developer" zurückgegeben.

Benutzerdefinierte Kontolabel unterscheiden sich von Anmelde- und Domainhinweisen dadurch, dass sie vollständig vom Identitätsanbieter-Server verwaltet werden und der vertrauende Dienst nur die zu verwendende Konfigurationsdatei angibt.

Hinweis: Benutzerdefinierte Kontolabel werden ab Chrome 132 unterstützt.

Beispiel für einen Antworttext:

  {
    "accounts": [{
      "id": "1234",
      "given_name": "John",
      "name": "John Doe",
      "email": "john_doe@idp.example",
      "picture": "https://idp.example/profile/123",
      // Ids of those RPs where this account can be used
      "approved_clients": ["123", "456", "789"],
      // This account has 'login_hints`. When an RP calls `navigator.credentials.get()`
      // with a `loginHint` value specified, for example, `exampleHint`, only those
      // accounts will be shown to the user whose 'login_hints' array contains the `exampleHint`.
      "login_hints": ["demo1", "exampleHint"],
      // This account is labelled. IdP can implement a specific config file for a
      // label, for example, `https://idp.example/developer-config.json`. Like that
      // RPs can filter out accounts by calling `navigator.credentials.get()` with
      // `https://idp.example/developer-config.json` config file.
      "label_hints": ["enterprise", "developer"]
    }, {
      "id": "5678",
      "given_name": "Johnny",
      "name": "Johnny",
      "email": "johnny@idp.example",
      "picture": "https://idp.example/profile/456",
      "approved_clients": ["abc", "def", "ghi"],
      "login_hints": ["demo2"],
      "domain_hints": ["@domain.example"]
    }]
  }

Wenn der Nutzer nicht angemeldet ist, antworte mit HTTP 401 (Nicht autorisiert).

Die zurückgegebene Kontoliste wird vom Browser verwendet und ist für den RP nicht verfügbar.

Endpunkt für die ID-Assertion

Der ID-Assertion-Endpunkt des IdP gibt eine Assertion für den angemeldeten Nutzer zurück. Wenn sich der Nutzer mit dem navigator.credentials.get()-Aufruf auf einer RP-Website anmeldet, sendet der Browser eine POST-Anfrage mit Cookies mit SameSite=None und dem Inhaltstyp application/x-www-form-urlencoded an diesen Endpunkt mit den folgenden Informationen:

Attribut Beschreibung
client_id (erforderlich) Die Client-ID des RP.
account_id (erforderlich) Die eindeutige ID des Nutzers, der sich anmeldet.
disclosure_text_shown Ergibt einen String mit "true" oder "false" (und keinen booleschen Wert). Das Ergebnis ist in diesen Fällen "false":
  • Wenn der Offenlegungstext nicht angezeigt wurde, weil die Client-ID des Rechtssubjekts in der approved_clients-Eigenschaftsliste der Antwort vom accounts-Endpunkt enthalten war.
  • Wenn der Offenlegungstext nicht angezeigt wurde, weil der Browser in der Vergangenheit ohne approved_clients eine Registrierung erkannt hat.
  • Wenn der Parameter fields nicht alle drei Felder („name“, „email“ und „picture“) enthält, z. B. fields=[ ] oder fields=['name', 'picture']. Dies ist für die Abwärtskompatibilität mit älteren Implementierungen erforderlich.

    Hinweis: Ab Chrome 141 wird der Offenlegungstext möglicherweise angezeigt, auch wenn der Wert disclosure_text_shown gleich "false" ist. Wenn Sie prüfen möchten, ob der Offenlegungstext angezeigt wurde, sehen Sie sich stattdessen den Wert disclosure_shown_for an.
disclosure_shown_for Hier werden die Felder aufgeführt, die der Browser dem Nutzer im Offenlegungstext angezeigt hat, um ihn darüber zu informieren, welche Daten der RP vom IdP anfordert.
is_auto_selected Wenn die automatische Re-Authentifizierung auf der RP erfolgt, gibt is_auto_selected "true" an. Andernfalls "false". Das ist hilfreich, um mehr sicherheitsrelevante Funktionen zu unterstützen. Einige Nutzer bevorzugen möglicherweise eine höhere Sicherheitsstufe, die eine explizite Nutzervermittlung bei der Authentifizierung erfordert. Wenn ein Identitätsanbieter eine Tokenanfrage ohne diese Vermittlung erhält, kann er die Anfrage anders bearbeiten. Geben Sie beispielsweise einen Fehlercode zurück, damit der RP die FedCM API noch einmal mit mediation: required aufrufen kann.
fields (optional) Array von Strings, das die Nutzerinformationen angibt, die der RP vom IdP angefordert hat. Die folgenden Felder können optional angegeben werden:
  • "name"
  • "username"
  • "email"
  • "tel"
  • "picture"
Der Browser sendet fields, disclosure_text_shown und disclosure_shown_for mit den angegebenen Feldern in der POST-Anfrage, wie im folgenden Beispiel.

Hinweis: Die Fields API wird von Chrome 132 und höher unterstützt. Die Felder „username“ und „tel“ werden ab Chrome 141 unterstützt.
params (optional) Ein beliebiges gültiges JSON-Objekt, mit dem zusätzliche benutzerdefinierte Schlüssel/Wert-Parameter angegeben werden können, z. B.:
  • scope: Ein Stringwert mit zusätzlichen Berechtigungen, die vom RP angefordert werden müssen, z. B. "drive.readonly calendar.readonly"
  • nonce: Ein zufälliger String, der vom RP bereitgestellt wird, um sicherzustellen, dass die Antwort für diese spezifische Anfrage ausgestellt wird. Verhindert Wiederholungsangriffe.
  • Andere benutzerdefinierte Parameter für Schlüssel/Wert-Paare.
Wenn der Browser eine POST-Anfrage sendet, wird der params-Wert in JSON serialisiert und dann prozentual codiert.

Hinweis: Die Parameters API wird von Chrome 132 und höher unterstützt.

Beispiel für HTTP-Header:

  POST /assertion.example HTTP/1.1
  Host: accounts.idp.example
  Origin: https://rp.example/
  Content-Type: application/x-www-form-urlencoded
  Cookie: 0x23223
  Sec-Fetch-Dest: webidentity

  // disclosure_text_shown is set to 'false', as the 'name' field value is missing in 'fields' array
  // params value is serialized to JSON and then percent-encoded.
  account_id=123&client_id=client1234&disclosure_text_shown=false&is_auto_selected=true&params=%22%7B%5C%22nonce%5C%22%3A%5C%22nonce-value%5C%22%7D%22.%0D%0A4&fields=email,picture&disclosure_shown_for=email,picture

Nach Erhalt der Anfrage sollte der Server Folgendes tun:

  1. Antworten Sie auf die Anfrage mit CORS (Cross-Origin Resource Sharing).
  2. Prüfen Sie, ob die Anfrage einen Sec-Fetch-Dest: webidentity-HTTP-Header enthält.
  3. Gleichen Sie den Origin-Header mit dem RP-Ursprung ab, der durch client_id bestimmt wird. Lehnen Sie die Anfrage ab, wenn sie nicht übereinstimmen.
  4. Vergleichen Sie account_id mit der ID des bereits angemeldeten Kontos. Lehne die Anfrage ab, wenn sie nicht übereinstimmen.
  5. Mit einem Token antworten. Wenn die Anfrage abgelehnt wird, antworte mit einer Fehlerantwort.

Der Identitätsanbieter kann entscheiden, wie er das Token ausstellt. Im Allgemeinen wird es mit Informationen wie der Konto-ID, der Client-ID, dem Ausstellerursprung und der Nonce signiert, damit der RP überprüfen kann, ob das Token echt ist.

Der Browser erwartet eine JSON-Antwort mit dem folgenden Attribut:

Attribut Beschreibung
token Ein Token ist ein String, der Behauptungen zur Authentifizierung enthält.
continue_on Weiterleitungs-URL, die einen mehrstufigen Anmeldevorgang ermöglicht.

Das zurückgegebene Token wird vom Browser an die vertrauende Partei übergeben, damit diese die Authentifizierung validieren kann.

  {
    // IdP can respond with a token to authenticate the user
    "token": "***********"
  }

Mit der Funktion fortfahren

Der IdP kann in der Antwort des ID-Assertion-Endpunkts eine Weiterleitungs-URL angeben, um einen mehrstufigen Anmeldevorgang zu ermöglichen. Das ist nützlich, wenn der Identitätsanbieter zusätzliche Informationen oder Berechtigungen anfordern muss, z. B.:

  • Berechtigung für den Zugriff auf die serverseitigen Ressourcen des Nutzers.
  • Bestätigung, dass die Kontaktdaten aktuell sind.
  • Jugendschutzeinstellungen

Der ID-Assertion-Endpunkt kann eine continue_on-Eigenschaft zurückgeben, die einen absoluten oder relativen Pfad zum ID-Assertion-Endpunkt enthält.

  {
    // In the id_assertion_endpoint, instead of returning a typical
    // "token" response, the IdP decides that it needs the user to
    // continue on a popup window:
    "continue_on": "https://idp.example/continue_on_url"
  }

Wenn die Antwort den Parameter continue_on enthält, wird ein neues Pop-up-Fenster geöffnet und der Nutzer wird zum angegebenen Pfad weitergeleitet. Nach der Nutzerinteraktion mit der Seite continue_on sollte der IdP IdentityProvider.resolve() mit dem als Argument übergebenen Token aufrufen, damit das Promise aus dem ursprünglichen navigator.credentials.get()-Aufruf aufgelöst werden kann:

  document.getElementById('example-button').addEventListener('click', async () => {
    let accessToken = await fetch('/generate_access_token.cgi');
    // Closes the window and resolves the promise (that is still hanging
    // in the relying party's renderer) with the value that is passed.
    IdentityProvider.resolve(accessToken);
  });

Der Browser schließt das Pop-up dann automatisch und gibt das Token an den API-Aufrufer zurück. Ein einmaliger IdentityProvider.resolve()-Aufruf ist die einzige Möglichkeit für das übergeordnete Fenster (RP) und das Pop-up-Fenster (IdP), miteinander zu kommunizieren.
Wenn der Nutzer die Anfrage ablehnt, kann der Identitätsanbieter das Fenster durch Aufrufen von IdentityProvider.close() schließen.

  IdentityProvider.close();

Für die Continuation API ist eine explizite Nutzerinteraktion (Klicks) erforderlich. So funktioniert die Continuation API mit verschiedenen Vermittlungsmodi:

  • Im passive-Modus:
    • mediation: 'optional' (Standard): Die Continuation API funktioniert nur mit einer Nutzeraktion, z. B. wenn ein Nutzer auf einen Button auf der Seite oder in der FedCM-Benutzeroberfläche klickt. Wenn die automatische Re-Authentifizierung ohne Nutzeraktion ausgelöst wird, wird kein Pop-up-Fenster geöffnet und das Promise wird abgelehnt.
    • mediation: 'required': Der Nutzer wird immer aufgefordert, zu interagieren, sodass die Continuation API immer funktioniert.
  • Im aktiven Modus:
    • Die Nutzeraktivierung ist immer erforderlich. Die Continuation API ist immer kompatibel.

Wenn der Nutzer aus irgendeinem Grund sein Konto im Pop-up-Fenster geändert hat (z. B. wenn der IdP die Funktion „Anderes Konto verwenden“ anbietet oder in Delegierungsfällen), akzeptiert der Resolve-Aufruf ein optionales zweites Argument, das Folgendes ermöglicht:

  IdentityProvider.resolve(token, {accountId: '1234');

Fehlerantwort zurückgeben

Die id_assertion_endpoint kann auch eine Fehlermeldung zurückgeben, die zwei optionale Felder hat:

  • code: Der IdP kann einen der bekannten Fehler aus der OAuth 2.0-Fehlerliste (invalid_request, unauthorized_client, access_denied, server_error und temporarily_unavailable) auswählen oder einen beliebigen String verwenden. Im letzteren Fall rendert Chrome die Fehler-UI mit einer allgemeinen Fehlermeldung und übergibt den Code an den RP.
  • url: Gibt eine für Menschen lesbare Webseite mit Informationen zum Fehler an, um Nutzern zusätzliche Informationen zum Fehler zu geben. Dieses Feld ist für Nutzer nützlich, da Browser keine ausführlichen Fehlermeldungen in einer integrierten Benutzeroberfläche bereitstellen können. Zum Beispiel Links für die nächsten Schritte oder Kontaktinformationen für den Kundenservice. Wenn ein Nutzer mehr über die Fehlerdetails und die Behebung des Fehlers erfahren möchte, kann er die angegebene Seite über die Browser-UI aufrufen. Die URL muss denselben Ursprung wie der IdP-configURL haben.
  // id_assertion_endpoint response
  {
    "error" : {
      "code": "access_denied",
      "url" : "https://idp.example/error?type=access_denied"
    }
  }
.

Benutzerdefinierte Kontolabels

Mit Benutzerdefinierte Kontolabels kann der IdP Nutzerkonten mit Labels versehen. Der RP kann dann nur Konten mit bestimmten Labels abrufen, indem er die configURL für das jeweilige Label angibt. Das kann nützlich sein, wenn ein RP Konten nach bestimmten Kriterien herausfiltern muss, um beispielsweise nur rollenspezifische Konten wie "developer" oder "hr" anzuzeigen.

Eine ähnliche Filterung ist mit den Funktionen Domain-Hinweis und Anmeldehinweis möglich, indem Sie sie im navigator.credentials.get()-Aufruf angeben. Mit benutzerdefinierten Kontolabels können Nutzer jedoch durch Angabe der Konfigurationsdatei gefiltert werden. Das ist besonders nützlich, wenn mehrere configURLs verwendet werden. Benutzerdefinierte Kontolabel unterscheiden sich auch dadurch, dass sie vom IdP-Server und nicht vom RP bereitgestellt werden, wie z. B. Anmelde- oder Domainhinweise.

Stellen Sie sich einen Identitätsanbieter vor, der zwischen "developer"- und "hr"-Konten unterscheiden möchte. Dazu muss der IdP zwei configURLs für "developer" bzw. "hr" unterstützen:

  • Die Entwicklerkonfigurationsdatei https://idp.example/developer/fedcm.json hat das Label "developer" und die Unternehmenskonfigurationsdatei https://idp.example/hr/fedcm.json hat das Label "hr":
  // The developer config file at `https://idp.example/developer/fedcm.json`
  {
    "accounts_endpoint": "https://idp.example/accounts",
    "client_metadata_endpoint": "/client_metadata",
    "login_url": "https://idp.example/login",
    "id_assertion_endpoint": "/assertion",
    "account_label": "developer"
  }
  // The hr config file at `https://idp.example/hr/fedcm.json`
  {
    "accounts_endpoint": "https://idp.example/accounts",
    "client_metadata_endpoint": "/client_metadata",
    "login_url": "https://idp.example/login",
    "id_assertion_endpoint": "/assertion",
    "account_label": "hr"
  }
  • Bei einer solchen Einrichtung sollte die well-known-Datei accounts_endpoint und login_url enthalten, um mehrere configURLs zu ermöglichen:
  {
    "provider_urls": [ "https://idp.example/fedcm.json" ],
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }
  • Der gemeinsame IdP-Kontenendpunkt (in diesem Beispiel https://idp.example/accounts) gibt eine Liste von Konten zurück, die für jedes Konto ein label_hints-Attribut mit zugewiesenen Labels in einem Array enthält:
  {
  "accounts": [{
    "id": "123",
    "given_name": "John",
    "name": "John Doe",
    "email": "john_doe@idp.example",
    "picture": "https://idp.example/profile/123",
    "label_hints": ["developer"]
    }], [{
    "id": "4567",
    "given_name": "Jane",
    "name": "Jane Doe",
    "email": "jane_doe@idp.example",
    "picture": "https://idp.example/profile/4567",
    "label_hints": ["hr"]
    }]
  }

Wenn ein RP "hr"-Nutzern die Anmeldung ermöglichen möchte, kann er die configURL https://idp.example/hr/fedcm.json im navigator.credentials.get()-Aufruf angeben:

  let { token } = await navigator.credentials.get({
    identity: {
      providers: [{
        clientId: '1234',
        nonce: '234234',
        configURL: 'https://idp.example/hr/fedcm.json',
      },
    }
  });

Daher kann sich der Nutzer nur mit der Konto-ID von 4567 anmelden. Die Konto-ID von 123 wird vom Browser ausgeblendet, damit dem Nutzer kein Konto angezeigt wird, das vom IdP auf dieser Website nicht unterstützt wird.

Zusätzliche Überlegungen:

  • Labels sind Strings. Wenn das label_hints-Array oder das account_label-Feld einen Wert verwendet, der kein String ist, wird der Wert ignoriert.
  • Wenn im configURL keine Labels angegeben sind, werden alle Konten in der FedCM-Kontoauswahl angezeigt.
  • Wenn für ein Konto keine Labels angegeben sind, wird es in der Kontoauswahl nur angezeigt, wenn für die configURL ebenfalls kein Label angegeben ist.
  • Wenn im passiven Modus kein Konto mit dem angeforderten Label übereinstimmt (ähnlich wie bei der Funktion „Domain-Hinweis“), wird im FedCM-Dialogfeld eine Anmeldeaufforderung angezeigt, über die sich der Nutzer in einem IdP-Konto anmelden kann. Im aktiven Modus wird das Pop-up-Fenster zur Anmeldung direkt geöffnet.

Endpunkt trennen

Durch den Aufruf von IdentityCredential.disconnect() sendet der Browser eine ursprungsübergreifende POST-Anfrage mit Cookies mit SameSite=None und einem Content-Type von application/x-www-form-urlencoded an diesen Endpunkt für die Trennung der Verbindung. Die Anfrage enthält die folgenden Informationen:

Attribut Beschreibung
account_hint Ein Hinweis zum IdP-Konto.
client_id Die Client-ID des RP.
  POST /disconnect.example HTTP/1.1
  Host: idp.example
  Origin: rp.example
  Content-Type: application/x-www-form-urlencoded
  Cookie: 0x123
  Sec-Fetch-Dest: webidentity

  account_hint=account456&client_id=rp123

Nach Erhalt der Anfrage sollte der Server Folgendes tun:

  1. Antworten Sie auf die Anfrage mit CORS (Cross-Origin Resource Sharing).
  2. Prüfen Sie, ob die Anfrage einen Sec-Fetch-Dest: webidentity-HTTP-Header enthält.
  3. Gleichen Sie den Origin-Header mit dem RP-Ursprung ab, der durch client_id bestimmt wird. Lehnen Sie die Anfrage ab, wenn sie nicht übereinstimmen.
  4. Gleichen Sie account_hint mit den IDs der bereits angemeldeten Konten ab.
  5. Trennen Sie die Verbindung des Nutzerkontos zur RP.
  6. Antworten Sie dem Browser mit den ermittelten Informationen zum Nutzerkonto im JSON-Format.

Eine Beispiel-JSON-Antwortnutzlast sieht so aus:

  {
    "account_id": "account456"
  }

Wenn der IdP stattdessen möchte, dass der Browser die Verbindung zu allen Konten trennt, die mit dem RP verknüpft sind, übergeben Sie einen String, der keiner Konto-ID entspricht, z. B. "*".

Endpunkt für Clientmetadaten

Der Clientmetadaten-Endpunkt des Identitätsanbieters gibt die Metadaten der vertrauenden Partei zurück, z. B. die Datenschutzerklärung, die Nutzungsbedingungen und die Logosymbole der vertrauenden Partei. RPs sollten dem IdP im Voraus Links zu ihrer Datenschutzerklärung und ihren Nutzungsbedingungen zur Verfügung stellen. Diese Links werden im Anmeldedialogfeld angezeigt, wenn sich der Nutzer noch nicht beim RP mit dem IdP registriert hat.

Der Browser sendet eine GET-Anfrage mit dem client_id navigator.credentials.get ohne Cookies. Beispiel:

  GET /client_metadata.example?client_id=1234 HTTP/1.1
  Host: accounts.idp.example
  Origin: https://rp.example/
  Accept: application/json
  Sec-Fetch-Dest: webidentity

Nach Erhalt der Anfrage sollte der Server Folgendes tun:

  1. Ermitteln Sie den RP für client_id.
  2. Antworte mit den Client-Metadaten.

Die Eigenschaften für den Endpunkt für Clientmetadaten umfassen:

Attribut Beschreibung
privacy_policy_url (optional) URL der Datenschutzerklärung für RP.
terms_of_service_url (optional) URL für die Nutzungsbedingungen für das RP.
icons (optional) Array von Objekten, z. B. [{ "url": "https://rp.example/rp-icon.ico", "size": 40}]

Der Browser erwartet eine JSON-Antwort vom Endpunkt:

  {
    "privacy_policy_url": "https://rp.example/privacy_policy.html",
    "terms_of_service_url": "https://rp.example/terms_of_service.html",
    "icons": [{
          "url": "https://rp.example/rp-icon.ico",
          "size": 40
      }]
  }

Die zurückgegebenen Clientmetadaten werden vom Browser verwendet und sind für die RP nicht verfügbar.

Anmelde-URL

Dieser Endpunkt wird verwendet, damit sich der Nutzer beim IdP anmelden kann.

Mit der Login Status API muss der IdP den Anmeldestatus des Nutzers an den Browser senden. Der Status kann jedoch nicht synchronisiert sein, z. B. wenn die Sitzung abläuft. In diesem Fall kann der Browser den Nutzer dynamisch über die Anmeldeseiten-URL, die mit login_url der IdP-Konfigurationsdatei angegeben wurde, beim IdP anmelden lassen.

Im FedCM-Dialogfeld wird eine Meldung angezeigt, in der ein Log-in vorgeschlagen wird, wie im folgenden Bild zu sehen ist.

Ein FedCM-Dialogfeld, in dem vorgeschlagen wird, sich beim IdP anzumelden.
Ein FedCM-Dialogfeld, in dem vorgeschlagen wird, sich beim IdP anzumelden.

Wenn der Nutzer auf die Schaltfläche Weiter klickt, öffnet der Browser ein Pop-up-Fenster für die Anmeldeseite des Identitätsanbieters.

Beispiel für ein FedCM-Dialogfeld
Beispiel für ein Dialogfeld, das nach dem Klicken auf die Schaltfläche „Beim Identitätsanbieter anmelden“ angezeigt wird.

Das Dialogfeld ist ein normales Browserfenster mit eigenen Cookies. Was im Dialogfeld passiert, liegt am IdP. Es sind keine Fensterhandles verfügbar, um eine ursprungsübergreifende Kommunikationsanfrage an die RP-Seite zu senden. Nachdem sich der Nutzer angemeldet hat, sollte der Identitätsanbieter Folgendes tun:

  • Senden Sie den Set-Login: logged-in-Header oder rufen Sie die navigator.login.setStatus("logged-in") API auf, um den Browser darüber zu informieren, dass der Nutzer angemeldet wurde.
  • Rufen Sie IdentityProvider.close() auf, um das Dialogfeld zu schließen.
Ein Nutzer meldet sich bei einem RP an, nachdem er sich mit FedCM beim IdP angemeldet hat.

Browser über den Anmeldestatus des Nutzers informieren

Die Login Status API (Anmeldestatus-API) ist ein Mechanismus, mit dem eine Website, insbesondere ein IdP, den Browser über den Anmeldestatus des Nutzers beim IdP informiert. Mit dieser API kann der Browser unnötige Anfragen an den Identitätsanbieter reduzieren und potenzielle Timing-Angriffe abwehren.

Identitätsanbieter können den Anmeldestatus des Nutzers an den Browser signalisieren, indem sie einen HTTP-Header senden oder eine JavaScript-API aufrufen, wenn der Nutzer beim Identitätsanbieter angemeldet ist oder wenn er sich von allen seinen Identitätsanbieterkonten abgemeldet hat. Für jeden IdP (identifiziert durch seine Konfigurations-URL) speichert der Browser eine Tristate-Variable, die den Anmeldestatus mit den folgenden möglichen Werten darstellt:

  • logged-in
  • logged-out
  • unknown (Standard)
Anmeldestatus Beschreibung
logged-in Wenn der Anmeldestatus des Nutzers auf logged-in gesetzt ist, sendet die RP, die FedCM aufruft, Anfragen an den Kontenendpunkt des IdP und zeigt dem Nutzer im FedCM-Dialog verfügbare Konten an.
logged-out Wenn der Anmeldestatus des Nutzers logged-out ist, schlägt der FedCM-Aufruf ohne Anfrage an den Kontenendpunkt des IdP fehl.
unknown (Standard) Der Status unknown wird festgelegt, bevor der Identitätsanbieter ein Signal über die Login Status API sendet. Wenn der Status unknown ist, sendet der Browser eine Anfrage an den Kontenendpunkt des Identitätsanbieters und aktualisiert den Status basierend auf der Antwort des Kontenendpunkts.

Senden Sie einen Set-Login: logged-in-HTTP-Header in einer Anfrage für die Navigation auf oberster Ebene oder für eine Same-Site-Unterressource am IdP-Ursprung, um zu signalisieren, dass der Nutzer angemeldet ist:

  Set-Login: logged-in

Alternativ können Sie die JavaScript-Methode navigator.login.setStatus('logged-in') über den IdP-Ursprung in einer Navigation auf oberster Ebene aufrufen:

  navigator.login.setStatus('logged-in')

Der Anmeldestatus des Nutzers wird auf logged-in gesetzt.

Um zu signalisieren, dass der Nutzer von allen seinen Konten abgemeldet ist, senden Sie einen Set-Login: logged-out-HTTP-Header in einer Navigation auf oberster Ebene oder einer Same-Site-Subressourcenanfrage am IdP-Ursprung:

  Set-Login: logged-out

Alternativ können Sie die JavaScript API navigator.login.setStatus('logged-out') über den IdP-Ursprung in einer Navigation der obersten Ebene aufrufen:

  navigator.login.setStatus('logged-out')

Der Anmeldestatus des Nutzers wird auf logged-out gesetzt.

Der Status unknown wird festgelegt, bevor der Identitätsanbieter ein Signal über die Login Status API sendet. Der Browser sendet eine Anfrage an den Kontenendpunkt des Identitätsanbieters und aktualisiert den Status basierend auf der Antwort des Kontenendpunkts:

  • Wenn der Endpunkt eine Liste aktiver Konten zurückgibt, aktualisieren Sie den Status auf logged-in und öffnen Sie das FedCM-Dialogfeld, um diese Konten anzuzeigen.
  • Wenn der Endpunkt keine Konten zurückgibt, aktualisieren Sie den Status auf logged-out und lassen Sie den FedCM-Aufruf fehlschlagen.

Nutzer über einen dynamischen Anmeldevorgang anmelden

Auch wenn der IdP den Anmeldestatus des Nutzers fortlaufend an den Browser sendet, kann es zu einer Abweichung kommen, z. B. wenn die Sitzung abläuft. Der Browser versucht, eine Anfrage mit Anmeldedaten an den Kontenendpunkt zu senden, wenn der Anmeldestatus logged-in ist. Der Server gibt jedoch keine Konten zurück, da die Sitzung nicht mehr verfügbar ist. In diesem Fall kann der Browser den Nutzer dynamisch über ein Pop-up-Fenster beim IdP anmelden.

Nächste Schritte

Implementiere FedCM für deine RPs und verteile das JavaScript SDK. RPs auf dem neuesten Stand halten, da keine manuelle Implementierung erforderlich ist
Hier erfahren Sie, wie Sie Ihre Umgebung einrichten und Ihre Implementierung debuggen.