FedCM-Updates: Ursprungstests für das Continuation API-Bundle und die automatische Zuweisung der Storage Access API

Ab Chrome 126 können Entwickler einen Ursprungstest für ein Paket von FedCM-Funktionen (Federated Credential Management API) für Desktop-Anwendungen ausführen, mit denen einige Autorisierungsfälle möglich sind. Das Bundle besteht aus der Continuation API und der Parameters API, die einen OAuth-Autorisierungsablauf mit einem von einem Identitätsanbieter bereitgestellten Berechtigungsdialog ermöglichen. Das Paket enthält auch andere Änderungen, z. B. die Fields API, mehrere configURLs und benutzerdefinierte Kontolabels. Ab Chrome 126 führen wir außerdem einen Test für die Storage Access API (SAA) ein, bei dem SAA-Anfragen automatisch gewährt werden, wenn sich der Nutzer in der Vergangenheit mit FedCM erfolgreich angemeldet hat.

Ursprungstest: FedCM Continuation API-Bundle

Das FedCM Continuation API-Bundle besteht aus mehreren FedCM-Erweiterungen:

Continuation API

Ein Nutzer meldet sich beim RP an und autorisiert dann über den Schaltflächenmodus.

Eine Demo der API auf Glitch

Mit der Continuation API kann der ID-Assertion-Endpunkt des IdP optional eine URL zurückgeben, die von FedCM gerendert wird, damit der Nutzer einen mehrstufigen Anmeldevorgang fortsetzen kann. So kann der IdP den Nutzer bitten, der vertrauenswürdigen Partei (RP) Berechtigungen zu gewähren, die über das hinausgehen, was in der vorhandenen FedCM-Benutzeroberfläche möglich ist, z. B. Zugriff auf die serverseitigen Ressourcen des Nutzers.

Normalerweise gibt der Endpunkt für die ID-Bestätigung ein Token zurück, das für die Authentifizierung erforderlich ist.

{
  "token": "***********"
}

Bei der Continuation API kann der Endpunkt für die ID-Bestätigung jedoch eine continue_on-Property zurückgeben, die einen absoluten oder relativen Pfad zum Endpunkt der ID-Bestätigung 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 pop-up window:
  "continue_on": "/oauth/authorize?scope=..."
}

Sobald der Browser die continue_on-Antwort erhält, wird ein neues Pop-up-Fenster geöffnet, über das der Nutzer zum angegebenen Pfad weitergeleitet wird.

Nachdem der Nutzer mit der Seite interagiert hat, z. B. eine weitere Berechtigung zur Weitergabe zusätzlicher Informationen an die RP erteilt hat, kann die IdP-Seite IdentityProvider.resolve() aufrufen, um den ursprünglichen navigator.credentials.get()-Aufruf aufzulösen und ein Token als Argument zurückzugeben.

document.getElementById('allow_btn').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 dann das Pop-up automatisch und gibt das Token an den API-Caller zurück.

Wenn der Nutzer die Anfrage ablehnt, kannst du das Fenster schließen, indem du IdentityProvider.close() aufrufst.

IdentityProvider.close();

Wenn der Nutzer aus irgendeinem Grund sein Konto im Pop-up geändert hat (z. B. wenn der IdP die Funktion „Nutzer wechseln“ anbietet oder bei der Delegierung), kann der resolve-Aufruf ein optionales zweites Argument annehmen, z. B.:

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

Parameters API

Mit der Parameters API kann der RP dem Endpunkt für die ID-Bestätigung zusätzliche Parameter zur Verfügung stellen. Mit der Parameters API können RPs zusätzliche Parameter an den IdP übergeben, um Berechtigungen für Ressourcen über die grundlegende Anmeldung hinaus anzufordern. Der Nutzer autorisiert diese Berechtigungen über einen vom Identitätsanbieter gesteuerten UX-Vorgang, der über die Continuation API gestartet wird.

Wenn Sie die API verwenden möchten, fügen Sie der params-Eigenschaft als Objekt im navigator.credentials.get()-Aufruf Parameter hinzu.

let {token} = await navigator.credentials.get({
  identity: {
    providers: [{
      clientId: '1234',
      configURL: 'https://idp.example/fedcm.json',
      // Key/value pairs that need to be passed from the
      // RP to the IdP but that don't really play any role with
      // the browser.
      params: {
        IDP_SPECIFIC_PARAM: '1',
        foo: 'BAR',
        ETC: 'MOAR',
        scope: 'calendar.readonly photos.write',
      }
    },
  }
});

Die Attributnamen im params-Objekt werden mit param_ vorangestellt. Im obigen Beispiel enthält das Attribut „params“ IDP_SPECIFIC_PARAM als '1', foo als 'BAR', ETC als 'MOAR' und scope als 'calendar.readonly photos.write'. Dies wird im HTTP-Text der Anfrage in param_IDP_SPECIFIC_PARAM=1&param_foo=BAR&param_ETC=MOAR&param_scope=calendar.readonly%20photos.write umgewandelt:

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

account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=false&param_IDP_SPECIFIC_PARAM=1&param_foo=BAR&param_ETC=MOAR&param_scope=calendar.readonly%20photos.write

Berechtigungen dynamisch abrufen

Im Allgemeinen ist es für Nutzer am hilfreichsten, Berechtigungen anzufordern, wenn sie benötigt werden, und nicht, wenn der Entwickler der Meinung ist, dass sie am einfachsten zu implementieren sind. Es ist beispielsweise besser, um die Berechtigung zum Zugriff auf eine Kamera zu bitten, wenn der Nutzer ein Foto aufnehmen möchte, als um die Berechtigung zu bitten, sobald der Nutzer die Website aufruft. Dasselbe gilt für Serverressourcen. Fordern Sie Berechtigungen nur an, wenn sie für den Nutzer erforderlich sind. Dies wird als „dynamische Autorisierung“ bezeichnet.

Um die Autorisierung dynamisch mit FedCM anzufordern, kann der IdP:

  1. Rufen Sie navigator.credentials.get() mit erforderlichen Parametern auf, die vom IdP verstanden werden können, z. B. scope.
  2. Der ID-Bestätigungsendpunkt bestätigt, dass der Nutzer bereits angemeldet ist, und antwortet mit einer continue_on-URL.
  3. Der Browser öffnet ein Pop-up-Fenster mit der Berechtigungsseite des Identitätsanbieters, in dem um eine zusätzliche Berechtigung gebeten wird, die den angeforderten Bereichen entspricht.
  4. Sobald die Autorisierung über IdentityProvider.resolve() durch den IdP erfolgt ist, wird das Fenster geschlossen und der ursprüngliche navigator.credentials.get()-Aufruf des RP erhält ein relevantes Token oder einen Autorisierungscode, damit der RP es gegen ein gültiges Zugriffstoken austauschen kann.

Fields API

Mit der Fields API kann der RP Kontoattribute angeben, die vom IdP angefordert werden sollen, damit der Browser im FedCM-Dialogfeld eine ordnungsgemäße Offenlegungs-UI anzeigen kann. Es liegt in der Verantwortung des IdP, die angeforderten Felder in das zurückgegebene Token aufzunehmen. Stellen Sie sich vor, Sie fordern ein „grundlegendes Profil“ in OpenID Connect an, anstatt „Bereiche“ in OAuth.

Offenlegungsmeldung im Widget-Modus
Offenlegungsmitteilung im Widget-Modus
Offenlegungsmitteilung im Schaltflächenmodus
Offenlegungsmitteilung im Schaltflächenmodus

Wenn Sie die Fields API verwenden möchten, fügen Sie der Eigenschaft fields im navigator.credentials.get()-Aufruf Parameter als Array hinzu. Die Felder können derzeit 'name', 'email' und 'picture' enthalten, können aber in Zukunft um weitere Werte erweitert werden.

Eine Anfrage mit fields würde so aussehen:

let { token } = await navigator.credentials.get({
  identity: {
    providers: [{
      fields: ['name', 'email', 'picture'],
      clientId: '1234',
      configURL: 'https://idp.example/fedcm.json',
      params: {
        scope: 'drive.readonly calendar.readonly',
      }
    },
  }
  mediation: 'optional',
});

Die HTTP-Anfrage an den Endpunkt für die ID-Bestätigung enthält den vom RP angegebenen Parameter fields. Der Parameter disclosure_text_shown ist auf true festgelegt, wenn es sich nicht um einen wiederkehrenden Nutzer handelt. Die Felder, die der Browser dem Nutzer in einem disclosure_shown_for-Parameter offengelegt hat, sind ebenfalls enthalten:

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

account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=true&fields=email,name,picture&disclosure_shown_for=email,name,picture

Wenn die RP auf zusätzliche Daten des Identitätsanbieters zugreifen muss, z. B. auf einen Kalender, sollte dies wie oben erwähnt mit einem benutzerdefinierten Parameter verwaltet werden. Der IdP gibt eine continue_on-URL zurück, um die Berechtigung anzufordern.

Wenn fields ein leeres Array ist, sieht die Anfrage so aus:

let { token } = await navigator.credentials.get({
  identity: {
    providers: [{
      fields: [],
      clientId: '1234',
      configURL: 'https://idp.example/fedcm.json',
      params: {
        scope: 'drive.readonly calendar.readonly',
      }
    },
  }
  mediation: 'optional',
});

Wenn fields ein leeres Array ist, überspringt der User-Agent die Benutzeroberfläche für die Offenlegung.

Die Offenlegungsmitteilung wird im Widget-Modus nicht angezeigt. Im Schaltflächenfluss wird die Benutzeroberfläche für die Offenlegung vollständig übersprungen.
Die Offenlegungsmitteilung wird im Widget-Modus nicht angezeigt. Im Schaltflächenfluss wird die Benutzeroberfläche für die Offenlegung vollständig übersprungen.

Das ist auch dann der Fall, wenn die Antwort vom Endpunkt „accounts“ keine Client-ID enthält, die mit der RP in approved_clients übereinstimmt.

In diesem Fall ist disclosure_text_shown, das an den ID-Bestätigungsendpunkt gesendet wird, im HTTP-Text „false“:

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

account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=false

Mehrere configURLs

Mit mehreren configURLs können IdPs mehrere Konfigurationsdateien für einen IdP verwenden. Dazu müssen accounts_endpoint und login_url in der Well-Known-Datei mit den Konfigurationsdateien identisch sein.

Wenn der .well-known-Datei accounts_endpoint und login_url hinzugefügt werden, werden die provider_urls ignoriert, damit der IdP mehrere Konfigurationsdateien unterstützen kann. Andernfalls wird provider_urls weiterhin angewendet, sodass die Funktion abwärtskompatibel ist.

Die „well-known“-Datei, die mehrere configURLs unterstützt, kann so aussehen:

{
  "provider_urls": [ "https://idp.example/fedcm.json" ],
  "accounts_endpoint": "https://idp.example/accounts",
  "login_url": "https://idp.example/login"
}

Dadurch können wir:

  1. Rückwärts- und Vorwärtskompatibilität mit vorhandenen bekannten Dateien und früheren Versionen von Browsern, die bereits im Einsatz sind.
  2. Sie können eine beliebige Anzahl von Konfigurationsdateien verwenden, solange sie alle auf dieselbe accounts_endpoint und login_url verweisen.
  3. Es gibt keine Möglichkeit, der an accounts_endpoint gesendeten Abrufanfrage mit Anmeldedaten Entropie hinzuzufügen, da sie auf „.well-known“-Ebene angegeben werden muss.

Die Unterstützung mehrerer configURLs ist optional und die vorhandenen FedCM-Implementierungen können unverändert bleiben.

Benutzerdefinierte Kontolabels

Mit benutzerdefinierten Kontolabels können FedCM-IdPs Konten annotieren, damit RPs sie durch Angabe des Labels in einer Konfigurationsdatei filtern können. Eine ähnliche Filterung war bereits mit der Domain Hint API und der Login Hint API möglich, indem sie im navigator.credentials.get()-Aufruf angegeben wurden. Mit den benutzerdefinierten Kontolabels können Nutzer jedoch durch Angabe der Konfigurationsdatei gefiltert werden. Das ist besonders nützlich, wenn mehrere configURLs verwendet werden. Benutzerdefinierte Kontolabels unterscheiden sich auch dadurch, dass sie vom IdP-Server und nicht vom RP bereitgestellt werden, z. B. Anmelde- oder Domainhinweise.

Beispiel

Ein Identitätsanbieter unterstützt jeweils zwei configURLs für Privatnutzer und Unternehmen. Die Konfigurationsdatei für Verbraucher hat ein 'consumer'-Label und die Konfigurationsdatei für Unternehmen ein 'enterprise'-Label.

Bei einer solchen Konfiguration enthält die „well-known“-Datei accounts_endpoint und login_url, um mehrere configURLs zuzulassen.

{
  "provider_urls": [ "https://idp.example/fedcm.json" ],
  "accounts_endpoint": "https://idp.example/accounts",
  "login_url": "https://idp.example/login"
}

Wenn die accounts_endpoint in der .well-known-Datei angegeben ist, werden die provider_urls ignoriert. Der RP kann im navigator.credentials.get()-Aufruf direkt auf die entsprechenden Konfigurationsdateien verweisen.

Die Konfigurationsdatei des Verbrauchers befindet sich unter https://idp.example/fedcm.json. Sie enthält das Attribut accounts, das 'consumer' mithilfe von include angibt.

{
  "accounts_endpoint": "https://idp.example/accounts",
  "client_metadata_endpoint": "/client_metadata",
  "login_url": "https://idp.example/login",
  "id_assertion_endpoint": "/assertion",
  "accounts": {
    "include": "consumer"
  }
}

Die Konfigurationsdatei für Unternehmen befindet sich unter https://idp.example/enterprise/fedcm.json. Sie enthält das Attribut accounts, das 'enterprise' mithilfe von include angibt.

{
  "accounts_endpoint": "https://idp.example/accounts",
  "client_metadata_endpoint": "/enterprise/client_metadata",
  "login_url": "https://idp.example/login",
  "id_assertion_endpoint": "/assertion",
  "accounts": {
    "include": "enterprise"
  }
}

Der gemeinsame IdP-Endpunkt für Konten (in diesem Beispiel https://idp.example/accounts) gibt eine Liste von Konten zurück, die für jedes Konto ein Label-Attribut mit zugewiesenem labels in einem Array enthält. Das folgende Beispiel zeigt eine Antwort für einen Nutzer mit zwei Konten. Eine Version ist für Privatnutzer und die andere für Unternehmen:

{
 "accounts": [{
   "id": "123",
   "given_name": "John",
   "name": "John Doe",
   "email": "john_doe@idp.example",
   "picture": "https://idp.example/profile/123",
   "labels": ["consumer"]
  }], [{
   "id": "4567",
   "given_name": "Jane",
   "name": "Jane Doe",
   "email": "jane_doe@idp.example",
   "picture": "https://idp.example/profile/4567",
   "labels": ["enterprise"]
  }]
}

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

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

Daher ist für die Anmeldung nur die Konto-ID von '4567' verfügbar. Die Konto-ID '123' wird vom Browser automatisch ausgeblendet, damit dem Nutzer kein Konto zugewiesen wird, das vom Identitätsanbieter auf dieser Website nicht unterstützt wird.

Ursprungstest: FedCM als Vertrauenssignal für die Storage Access API

In Chrome 126 beginnt ein Ursprungstest für FedCM als Vertrauenssignal für die Storage Access API. Durch diese Änderung ist eine vorherige Berechtigungserteilung über FedCM ein gültiger Grund, einen Speicherzugriffsanfrage über die Storage Access APIs automatisch zu genehmigen.

Das ist nützlich, wenn ein eingebetteter iFrame auf personalisierte Ressourcen zugreifen soll, z. B. wenn idp.beispiel in rp.beispiel eingebettet ist und eine personalisierte Ressource angezeigt werden muss. Wenn der Browser den Zugriff auf Drittanbieter-Cookies einschränkt, kann der eingebettete idp.example-Frame keine personalisierten Ressourcen anfordern, auch wenn der Nutzer mit FedCM über idp.example in rp.beispiel angemeldet ist. Das liegt daran, dass Anfragen keine Drittanbieter-Cookies enthalten.

Dazu muss idp.beispiel über den auf der Website eingebetteten Iframe eine Berechtigung zum Speicherzugriff erhalten. Diese kann nur über eine Berechtigungsanfrage abgerufen werden.

Wenn FedCM als Vertrauenssignal für die Storage Access API verwendet wird, werden bei den Berechtigungsprüfungen der Storage Access API nicht nur die Berechtigungen akzeptiert, die über einen Prompt für den Speicherzugriff erteilt werden, sondern auch die Berechtigungen, die über einen FedCM-Prompt erteilt werden.

// In top-level rp.example:

// Ensure FedCM permission has been granted.
const cred = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: 'https://idp.example/fedcm.json',
      clientId: '123',
    }],
  },
  mediation: 'optional',
});

// In an embedded IdP iframe:

// No user gesture is needed to call this, and the call will be auto-granted.
await document.requestStorageAccess();

// This returns `true`.
const hasAccess = await document.hasStorageAccess();

Sobald sich der Nutzer mit FedCM angemeldet hat, wird die Berechtigung automatisch gewährt, solange die FedCM-Authentifizierung aktiv ist. Das bedeutet, dass nach der Verbindungsunterbrechung eine Aufforderung zur Berechtigungsanfrage angezeigt wird.

Am Ursprungstest teilnehmen

Sie können das FedCM Continuation API-Bundle lokal testen, indem Sie in Chrome 126 oder höher eine Chrome-Flag aktivieren. chrome://flags#fedcm-authz Sie können FedCM auch lokal als Vertrauenssignal für die Storage Access API verwenden. Aktivieren Sie dazu #fedcm-with-storage-access-api in Chrome 126 oder höher.

Diese Funktionen sind auch als Ursprungstests verfügbar. Mit Ursprungstests kannst du neue Funktionen ausprobieren und Feedback zu ihrer Nutzerfreundlichkeit, Praktikabilität und Wirksamkeit geben. Weitere Informationen finden Sie im Hilfeartikel Einstieg in Ursprungstests.

Wenn Sie den Ursprungstest für das FedCM Continuation API-Bundle ausprobieren möchten, erstellen Sie zwei Ursprungstest-Tokens:

Wenn Sie die Continuation API zusammen mit dem Schaltflächenfluss aktivieren möchten, aktivieren Sie auch den Test für den API-Ursprung des Schaltflächenmodus:

So testen Sie FedCM als Vertrauenssignal für den Ursprungstest der Storage Access API:

Der Ursprungstest für das Continuation API-Bundle und FedCM als Vertrauenssignal für den Ursprungstest der Storage Access API sind ab Chrome 126 verfügbar.

Ursprungstest für Drittanbieter für den RP registrieren

  1. Rufe die Seite zur Registrierung für den Testzugriff auf.
  2. Klicken Sie auf die Schaltfläche Registrieren und füllen Sie das Formular aus, um ein Token anzufordern.
  3. Geben Sie den Ursprung des IdP als Web-Ursprung ein.
  4. Aktivieren Sie die Option „Drittanbieterabgleich“, um das Token mit JavaScript in anderen Ursprüngen einzuschleusen.
  5. Klicken Sie auf Senden.
  6. Binde das ausgestellte Token auf einer Drittanbieter-Website ein.

Wenn Sie das Token auf einer Drittanbieterwebsite einbetten möchten, fügen Sie der JavaScript-Bibliothek oder dem SDK des Identitätsanbieters, das vom Ursprung des Identitätsanbieters bereitgestellt wird, den folgenden Code hinzu.

const tokenElement = document.createElement('meta');
tokenElement.httpEquiv = 'origin-trial';
tokenElement.content = 'TOKEN_GOES_HERE';
document.head.appendChild(tokenElement);

Ersetzen Sie TOKEN_GOES_HERE durch Ihr eigenes Token.