Federated Credential Management API

Draft Community Group Report,

This version:
https://fedidcg.github.io/FedCM/
Test Suite:
https://github.com/web-platform-tests/wpt/blob/master/credential-management/webid.https.html
Issue Tracking:
GitHub
Inline In Spec
Editor:
(Google Inc.)

Abstract

A Web Platform API that allows users to login to websites with their federated accounts in a privacy preserving manner.

Status of this document

This specification was published by the Federated Identity Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

1. Introduction

This section is non-normative.

As the web has evolved there have been ongoing privacy-oriented changes (e.g Safari, Firefox, Chrome) and changes to the underlying privacy principles (e.g. Privacy Model).

With this evolution, fundamental assumptions of the web platform are being redefined or removed. Access to cookies in a third-party context are one of those assumptions. While overall good for the web, the third-party cookie deprecation removes a fundamental building block used by certain designs of federated identity.

The Federated Credential Management API aims to bridge the gap for the federated identity designs which relied on third-party cookies. The API provides the primitives needed to support federated identity when/where it depends on third-party cookies, from sign-in to sign-out and revocation.

In order to provide the federated identity primitives without the use of third-party cookies the API places the user agent as a mediator between RPs and IDPs. This mediation requires user consent before permitting the RPs and IDPs to know about their connection to the user.

The specification leans heavily on changes in the user agent and IDP and minimally on the RP. The FedCM API provides a way to authenticate, fetch tokens, revoke the provided tokens, and allow for front-channel logout.

1.1. Use Cases

The below use case scenarios illustrate some basic supported flows. Each supported flow below occurs inside an iframe or in an XHR request. Additional scenarios, including sample code, are given in the Identity Use Cases in Browser Catalog.

1.1.1. Sign-up

A Sign-up occurs when the user is registering a new account at the Relying Party using their Identity Provider.

For instance, a user navigates to a Relying Party in their browser and creates an account. The Relying Party displays supported Identity Providers to the user who selects their favorite. The user is prompted "Do you want to create an account with the Relying Party?". Upon user agreement an account is created with the Relying Party and the user has a session initialized.

1.1.2. Sign-in

After a user navigates to a Relying Party in a browser and decides to create an account by going through their § 1.1.1 Sign-up flow, there are two ways a user logs into their account once their session expires:

1.1.2.1. Auto Sign-in

Auto Sign-in occurs when the Identity Provider has already gathered permissions from the user to share their identity with the Relying Party and automatically signs the user in.

For example, the user has previously executed the § 1.1.1 Sign-up flow and then changes from their phone to their laptop. On the new device the user goes to the Relying Party and selects to sign-in using their Identity Provider. The Identity Provider knows, and proves, the user has signed up to the Relying Party and the Relying Party creates a new session for the users account.

1.1.2.2. Explicit Sign-in

An explicit sign-in occurs when the Identity Provider believes it is necessary to gather an explicit permission from the user to sign into a Relying Party, typically after the user goes through a § 1.1.3 Sign-out flow.

For example, after the user has done the § 1.1.3 Sign-out flow of the Relying Party they decide to log in again. The user visits the Relying Party and selects their Identity Provider to sign-in. The Identity Provider knows:

The user is then prompted, "Do you want to sign-in with the Relying Party?" and upon user agreement the Relying Party creates a new session with the users existing account.

1.1.3. Sign-out

After a user navigates to a Relying Party in a browser and decides to create an account by going through their § 1.1.1 Sign-up flow, there are two ways a user can clear their sessions:

1.1.3.1. RP Sign-out

The user can log out through the Relying Party by using a provided sign-out button or link provided by the Relying Party. This then removes the users session and, when the user visits the Relying Party again they will need to go through the § 1.1.2.2 Explicit Sign-in flow in order to establish a new session.

1.1.3.2. IDP Sign-out

The user can log out through the Identity Provider by using a provided sign-out system provided by the Identity Provider. After using the sign-out system the Identity Provider will log the user out of all Relying Parties the user has signed into along with logging the user out of the Identity Provider itself. Upon returning to any associated Relying Party, or the Identity Provider, the user will have to go through the § 1.1.2.2 Explicit Sign-in flow.

1.1.4. Revocation

After a user has created an account with a Relying Party there are two ways a user can cancel their account with the Relying Party:

1.1.4.1. RP Revocation

The user can delete their account through the Relying Party by using the provided cancel account system. The Relying Party informs the Identity Provider that the user has deleted (revoked) their account. When the user returns to the Relying Party they will need to complete the § 1.1.1 Sign-up flow in order to access the site.

1.1.4.2. IDP Revocation

The user can delete their account with a Relying Party by revoking Relying Party access through the Identity Provider. This can be done by going to the Identity Provider and using their revoke access system. Once access is revoked, when the user returns to the Relying Party they will need to complete the § 1.1.1 Sign-up flow in order to access the site.

1.1.5. Access

The Identity Provider while authenticating the user may also authorize access to users resources such as calendars, contacts, etc. The granting of access can be done at either sign-up or post sign-up by requesting permission from the user.

For example, a user executes the § 1.1.1 Sign-up flow with a Relying Party. During the flow the Relying Party has informed the Identity Provider they need calendar access for the user. The user will be presented with a prompt, "Do you want to give access to your Calendar to the Relying Party?". The user consents to providing access and when the flow is complete the Relying Party shows the user their calendar entries provided by the Identity Provider.

2. Examples

This specification defines a new IdentityCredential type and internal algorithms to allow the exchange of identity between IDPs and RPs. When it succeeds, it returns to the RP a signed token which the RP can use to authenticate the user.

Example showing how a website allowing for a single logged in account could be implemented.
<html>
<head>
  <title>Welcome to my Website</title>
</head>
<body>
  <button onclick="login()">Login with idp.example</button>

  <script>
  let nonce;
  async function login() {
    // Assume we have a method returning a random number. Store the value in a variable which can
    // later be used to check against the value in the token returned.
    nonce = random();
    // Prompt the user to select an account from the IDP to use for
    // federated login within the RP. If resolved successfully, the Promise
    // returns an IdentityCredential object from which the <code data-opaque bs-autolink-syntax='`token`'>token</code> can be
    // extracted.
    return await navigator.credentials.get({
      mediation: "optional", // "optional" is the default
      identity: {
        providers: [{
          configURL: "https://idp.example/manifest.json",
          clientId: "123",
          nonce: nonce
        }]
      }
    });
  }
  </script>
</body>
</html>

3. Terminology

HTML Standard defines an origin as the tuple of a scheme, hostname, and port that provides the main security boundary on the web.

account

TODO(goto): find existing definition.

authentication

Process used by an Identity Provider to achieve sufficient confidence in the binding between the user and a presented identity.

Note that in some discussions and documentation, the term _authentication_ is used to refer to the federated sign-in process. However, the user does not authenticate to the RP during federated sign-in. The user authenticates to the IDP, which then provides a claim to the RP asserting the user’s identity. The user does not prove their identity to the RP.

See also:

client id

Each IDP assigns to each RP a client id to uniquely identify the RP. Note that this ID is dependent on both the IDP and the RP, but the client id of an RP only needs to be unique with respect to any other client id within the same IDP.

directed identifier

A user identifier that that is unique for each site the user visits. A goal of anti-tracking policy is to promote user identifiers to become directed identifiers.

global identifier

A string that identifies a particular user independent of which site they’re visiting (e.g. email addresses and phone numbers). Users generally have relatively few global identifiers and can usually list and recognize them. A goal of anti-tracking policy is to prevent user identifiers from becoming global identifiers.

high-level API

A use case specific API, as opposed to a low-level API. See also high level vs low level.

token

TODO(goto): find existing definition.

Identity Provider
IDP

A service that has information about the user and can grant that information to Relying Parties.

See also:

Tracker

A third-party origin that has injected a script within the RP and that is not an IDP. Its goal is to track the user’s behavior and build profiles that it can then sell to the highest bidder.

joining

TODO(goto): find existing definition.

low-level API

A general purpose API, as opposed to a high-level API. See also high level vs low level

minting

The act of a new token being creating

out-of-band

Outside of the user agent’s context.

Relying Party
RP
Website

A service that requests user information from an Identity Provider for federated sign-in or for other purposes.

See also:

session

TODO(goto): find existing definition.

Federated sign-in

Process used by a Relying Party to obtain a user identifier from an Identity Provider to which the user performed authentication.

See also:

site

A set of origins that are all same site with each other. Note that there are problems (Public Suffix List Problems) with using registrable domains as a logical boundary.

unsanctioned tracking

Unsanctioned Web Tracking

user

A human or program that controls a user agent.

user identifier

A pair of a site and a (potentially-large) integer allocated by that site that is used to identify a user on that site. A single user will generally have many user IDs that refer to them, and a single site may or may not know that multiple user identifiers refer to the same user.

Privacy Policy

The policies described at privacy_policy_url.

Terms of Service

The policies described at terms_of_service_url.

registered

The account is registered if the user agent thinks that the user has registered an account in the RP using the account from the IDP.

unregistered

The account is unregistered if it’s not registered.

4. High Level Design

At a high level, the Identity Federation Management API works by the intermediation of cooperating IDPs and RPs.

The § 5 The Identity Provider API and the § 6 The Relying Party API defines a set of HTTP APIs that cooperating IDPs and IDPs exposes as well as the entry points in the § 7 The Browser API that they can use.

The user agent intermediates in such a matter that makes it impractical for the API to be used for tracking purposes, while preserving the functionality of identity federation.

This document defines the APIs in the following order:

  1. The § 5 The Identity Provider API

  2. The § 6 The Relying Party API

  3. The § 7 The Browser API

5. The Identity Provider API

The IDP proactively and cooperatively exposes itself as a comformant agent by exposing a series of HTTP endpoints:

  1. A § 5.1 Manifest endpoint in an agreed upon location that points to

  2. An § 5.2 Accounts List endpoint

  3. A § 5.3 Client Metadata endpoint

  4. An § 5.4 ID Token endpoint

5.1. Manifest

The manifest discovery endpoint is an endpoint which serves as a discovery device to other endpoints provided by the IDP.

The manifest discovery endpoint is fetched:

(a) without cookies, (b) with a special § 5.5 Sec-FedCM-CSRF header, (c) without a Referer header, and (c) without following HTTP redirects.

For example:

GET /config.json HTTP/1.1
Host: idp.example
Accept: application/json
Sec-FedCM-CSRF: ?1

The file is parsed expecting Manifest JSON object.

The Manifest JSON object has the following properties:

accounts_endpoint (required)

A URL that points to an HTTP API that complies with the § 5.2 Accounts List API.

client_metadata_endpoint (required)

A URL that points to an HTTP API that complies with the § 5.3 Client Metadata API.

id_token_endpoint (required)

A URL that points to an HTTP API that complies with the § 5.4 ID Token API.

branding (optional)

A set of Branding JSON options.

The Branding JSON enables an IDP to express their branding preferences, which may be used by user agents to customize the consent prompt.

Note: The branding preferences are deliberately designed to be high level / abstract (rather than opinionated about a specific UI structure), to enable different user agents to offer different UI experiences and for them to evolve independently over time.

It may have the following properties:

background_color (optional)

Background color for IDP-branded widgets such as buttons.

color (optional)

color for text on IDP branded widgets.

icons (optional)

A list of Icon JSON objects.

Note: The branding preferences are deliberately designed to be high level / abstract (rather than opinionated about a specific UI structure), to enable different user agents to offer different UI experiences and for them to evolve independently over time.

The Icon JSON may have the following properties:

url (required)

The url pointing to the icon image, which must be square and single resolution (not a multi-resolution .ico). The icon needs to comply with the maskable specification.

size (optional)

The width/height of the square icon. The size may be omitted if the icon is in a vector graphic format (like SVG).

Note: the user agent reserves a square size for the icons provided by the developer. If the developer provides an icon that is not square, the user agent may choose to not display it at all, trim the icon and show a square portion of it, or even transform it into a square icon and show that.

The color is a subset of CSS <color> syntax, namely <hex-color>s, hsl()s, rgb()s and <named-color>.

For example:

{
  "accounts_endpoint": "/accounts.php",
  "client_metadata_endpoint": "/metadata.php",
  "id_token_endpoint": "/idtokens.php",
  "branding": {
    "background_color": "green",
    "color": "0xFFEEAA",
    "icons": [{
      "url": "https://idp.example/icon.ico",
      "size": 10
    }]
  }
}

5.2. Accounts List

The accounts list endpoint provides the list of accounts the user has at the IDP.

The accounts list endpoint is fetched (a) with IDP cookies, (b) with a special § 5.5 Sec-FedCM-CSRF header, (c) without a Referer header, and (d) without following HTTP redirects.

For example:

GET /accounts_list.php HTTP/1.1
Host: idp.example
Accept: application/json
Cookie: 0x23223
Sec-FedCM-CSRF: ?1

The response is expected to have the following properties:

accounts (required)

A list of Account JSON.

Every Account JSON is expected to have the following properties:

id (required)

The account unique identifier.

name (required)

The user’s full name.

email (required)

The user’s email address.

given_name (optional)

The user’s given name.

approved_clients (optional)

A list of RPs (in the form of Client IDs) this account is already registered with. Used in the request consent to sign-up to allow the IDP to control whether to show the Privacy Policy and the Terms of Service.

For example:

{
 "accounts": [{
   "id": "1234",
   "given_name": "John",
   "name": "John Doe",
   "email": "john_doe@idp.example",
   "picture": "https://idp.example/profile/123",
   "approved_clients": ["123", "456", "789"]
  }, {
   "id": "5678",
   "given_name": "Johnny",
   "name": "Johnny",
   "email": "johnny@idp.example",
   "picture": "https://idp.example/profile/456"
   "approved_clients": ["abc", "def", "ghi"]
  }]
}

5.3. Client Metadata

The client metadata endpoint provides metadata about RPs.

The client medata endpoint is fetched (a) without cookies, (b) with a special § 5.5 Sec-FedCM-CSRF header, (c) with a Referer header indicating the RP's origin (as if Referer-Policy: strict-origin was in use), and (d) without following HTTP redirects.

The user agent also passes the client_id.

For example:

GET /client_medata.php?client_id=1234 HTTP/1.1
Host: idp.example
Referer: https://rp.example/
Accept: application/json
Sec-FedCM-CSRF: ?1

The file is parsed expecting the following properties:

privacy_policy_url (optional)

A link to the RP's privacy policy.

terms_of_service_url (optional)

A link to the RP's terms of service.

For example:

{
  "privacy_policy_url": "https://rp.example/clientmetadata/privacy_policy.html",
  "terms_of_service_url": "https://rp.example/clientmetadata/terms_of_service.html"
}

5.4. ID Token

The ID Token endpoint is responsible for minting a new token for the user.

The ID Token endpoint is fetched (a) as a POST request, (b) with IDP cookies, (c) with a Referer header indicating the RP's origin (as if Referer-Policy: strict-origin was in use), (d) with a special § 5.5 Sec-FedCM-CSRF header, and (e) without following HTTP redirects.

It will also contain the following parameters in the request body application/x-www-form-urlencoded:

client_id

The RP's client id.

nonce

The request nonce

account_id

The account identifier that was selected.

disclosure_text_shown

Whether the user agent has explicitly shown to the user what specific information the IDP intends to share with the RP (e.g. "idp.example will share your name, email... with rp.example"), used by the request consent to sign-up algorithm for new users but not by the sign-in algorithm for returning users.

For example:

POST /fedcm_token_endpoint HTTP/1.1
Host: idp.example
Referer: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-FedCM-CSRF: ?1
account_id=123&client_id=client1234&nonce=Ct60bD&disclosure_text_shown=true

The response is parsed as a JSON file expecting the following properties:

token

The resulting token.

For example:

{
  "token" : "eyJC...J9.eyJzdWTE2...MjM5MDIyfQ.SflV_adQssw....5c"
}

5.5. Sec-FedCM-CSRF

All FedCM HTTP requests sent by the browser must contain a header Sec-FedCM-CSRF with value ?1. This allows servers to verify that the request was initiated by the browser and not untrusted JavaScript because it is a forbidden header name.

6. The Relying Party API

RPs expose a § 6.1 Logout to facilitate with § 1.1.3.2 IDP Sign-out.

6.1. Logout

When IDPs call the § 7.4.1 IDP Sign-out API, every RP gets a chance to log the user out (e.g. clear cookies, clear local storage) via the logout endpoint.

The logout endpoint is an endpoint that is registered with the IDP out-of-band.

The logout endpoint is called (a) with a GET and (b) with the RP's cookies.

Note: the logout API introduces a credentialed request from the IDP to the RPs, so it exposes a potential tracking surface area. It is a fairly limited and controlled tracking area because the logout API is only available when accounts and sessions are already established between the IDP and the RP.

7. The Browser API

The Browser API exposes APIs to RPs and IDPs to call and intermediates the exchange of the user’s identity.

The Sign-up and Sign-in APIs are used by the Relying Partys to ask the browser to intermediate the relationship with the Identity Provider and the provisioning of a token.

NOTE: The Relying Party makes no delineation between Sign-up and Sign-in, but rather calls the same API indistinguishably.

If all goes well, the Relying Party receives back an IdentityCredential which contains a token in the form of a signed JWT which it can use to authenticate the user.

const credential = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: "https://idp.example/manifest.json",
      clientId: "123",
    }]
  }
});

To do so, this specification does three things:

First, it introduces a new Credential type, called IdentityCredential.

Second, it introduces an extension to CredentialRequestOptions.

Lastly, it overrides IdentityCredential's implementation of [[DiscoverFromExternalSource]].

7.1. The State Machine

Each user agent keeps track of a global state machine map, an initially empty map. The keys in the state machine map are triples of the form (rp, idp, account) where rp is the origin of the RP, idp is the origin of the IDP, and account is a string representing an account identifier. The values in the state machine map are AccountState objects which have the following properties:

registration state

Keeps track of whether the user agent is aware that the user has registered an account in the RP or not. Can be registered or unregistered (by default).

allows logout

Boolean which keeps track of whether the user agent would allow the account to be logged out via logoutRPs(). It is initialized to false by default. Note that this value being true does not imply that the user is logged in to the RP with the account, it merely implies that logoutRPs() has not yet been called on this account after the last successful IdentityCredential creation with this account.

TODO: add an ASCII image to explain how the states fit into the algorithms.

7.2. The IdentityCredential Interface

This specification introduces a new type of Credential, called an IdentityCredential:

[Exposed=Window, SecureContext]
interface IdentityCredential : Credential {
  readonly attribute USVString? token;
};
token

The token's attribute getter returns the value it is set to. It represents the minted token provided by the IDP.

The main entrypoint in this specification is through the entrypoints exposed by the Credential Management API.

7.3. The CredentialRequestOptions

This specification starts by introducing an extension to the CredentialRequestOptions object:

partial dictionary CredentialRequestOptions {
  IdentityCredentialRequestOptions identity;
};

The IdentityCredentialRequestOptions contains a list of IdentityProviders that the Relying Party supports and has pre-registered with (i.e. it has a clientId).

dictionary IdentityCredentialRequestOptions {
  sequence<IdentityProvider> providers;
};

Each IdentityProvider represents an Identity Provider that the Relying Party supports (e.g. that it has a pre-registration agreement with).

dictionary IdentityProvider {
  required USVString configURL;
  required USVString clientId;
  USVString nonce;
};
configURL

The URL of the configuration file for the identity provider.

clientId

The client id provided to the RP out of band by the IDP

nonce

A random number of the choice of the RP. It is generally used to associate a client session with a token and to mitigate replay attacks. Therefore, this value should have sufficient entropy such that it would be hard to guess.

7.4. The [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) internal method

The [[DiscoverFromExternalSource]] algorithm runs in parallel inside the Credential Management § algorithm-request to request credentials and returns a set of IdentityCredential for the requested Identity Providers.

This internal method accepts three arguments:

origin

This argument is the relevant settings object's origin, as determined by the calling get() implementation, i.e., CredentialsContainer's Request a Credential abstract operation.

options

This argument is a CredentialRequestOptions object whose identity member contains an IdentityCredentialRequestOptions object specifying the exchange options.

sameOriginWithAncestors

This argument is a Boolean value which is true if and only if the caller’s environment settings object is same-origin with its ancestors. It is false if caller is cross-origin.

NOTE: The mediation flag is currently not used.

The signal is used as an abort signal for the requests.

When the IdentityCredential's [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)\ algorithm is invoked, the user agent MUST execute the following steps:
  1. If sameOriginWithAncestors is false, throw a "NotAllowedError" DOMException.

    Note: This restriction aims to address the concern raised in Security Origin Confusion.

  2. Assert: options["identity"]["providers"] exists.

  3. Assert: options["identity"]["providers"] size is 1.

    Note: At some point we would like to support choosing accounts from multiple Identity Providers.

  4. Run setTimeout passing a task which throws a NetworkError, after a timeout of 120 seconds.

    Note: the purpose of having a timer here is to avoid leaking the reason causing this method to return null. If there was no such timer, the developer could easily infer whether the user has an account with the IDP or not, or whether the user closed the UI without providing consent to share the IDP account information with the RP.

  5. Let provider be options["identity"]["providers"][0].

  6. Let credential be the result of running the potentially create IdentityCredential algorithm with provider.

  7. If credential is null, wait for the task that throws a NetworkError, otherwise return credential.

To potentially create IdentityCredential, given an IdentityProvider provider:
  1. Let manifest be the result of running the fetch the manifest algorithm with provider.

  2. If manifest is null, return null.

  3. Let accountsList be the result of running the fetch the accounts list algorithm with manifest and provider.

  4. If accountsList’s size is 0, return null.

  5. If accountsList’s size is 1:

    1. Let account be accountsList[0].

    2. Let accountState be the result of running the compute account state algorithm given provider and account.

    3. If accountState’s registration state is unregistered then run the request consent to sign-up algorithm with account, accountState, manifest, and provider.

    4. Otherwise, show a dialog to request user consent to sign in via account.

    5. If the user consents, run the sign-in algorithm with accountState.

  6. Otherwise:

    1. Let account be the result of running the select an account from the accountsList.

    2. If account is null, return null.

    3. Let accountState be the result of running the compute account state algorithm given provider and account.

    4. If accountState’s registration state is unregistered then run the request consent to sign-up algorithm with account, accountState, manifest, and provider.

    5. Otherwise, run the sign-in algorithm with accountState.

  7. If accountState’s registration state is unregistered then return null.

  8. Let token be the result of running the create tokens algorithm with accountState, account’s id, and provider.

  9. Let credential be a new IdentityCredential.

  10. Set credential’s token to token.

  11. Return credential.

To compute account state given an IdentityProvider provider and an Account JSON account, run the following steps:
  1. Let idpURL be provider’s configURL.

  2. Let idpOrigin be the origin corresponding to idpURL.

  3. Let rpOrigin be this's origin.

  4. Let accountId be account’s id.

  5. Let triple be (rpOrigin, idpOrigin, accountId).

  6. If state machine map[triple] does not exist, set state machine map[triple] to a new AccountState.

  7. Let accountState be state machine map[triple].

  8. Return accountState.

To fetch the accounts list given a Manifest manifest and an IdentityProvider provider:
  1. Let the accountsEndpoint url be the relative url manifest["accounts_endpoint"] of provider’s configURL.

  2. Let accountsList be the result of fetching the accountsEndpoint with the Identity Provider's cookies. This request MUST NOT follow HTTP redirects and instead return null if there is any error. See also § 5.2 Accounts List.

  3. Return accountsList.

the fetch the accounts list algorithm needs to use fetch appropriately.

To request consent to sign-up the user with a given Account JSON account, an AccountState accountState, a Manifest manifest, and an IdentityProvider provider:
  1. Let metadata be the result of running the fetch the client metadata algorithm with manifest and provider.

  2. If metadata is not null, metadata["privacy_policy_url"] is defined, and the provider’s clientId is not in the list of account["approved_clients"], then display the metadata["privacy_policy_url"] link.

  3. If metadata is not null, metadata["terms_of_service_url"] is defined, and the provider’s clientId is not in the list of account["approved_clients"], then display the metadata["terms_of_service_url"] link.

  4. Prompt the user to gather explicit intent to create an account. The user agent MAY use the Branding JSON to inform the style choices of its UI.

  5. If the user does not provide consent, return.

  6. Change accountState’s registration state from unregistered to registered.

  7. Change accountState’s allows logout from false to true.

To fetch the client metadata given a Manifest manifest and an IdentityProvider provider, run the following steps:
  1. Let the clientMetadataEndpoint url be the relative url manifest["client_metadata_endpoint"] of provider’s configURL.

  2. Let the clientMetadata be the result of fetching the clientMetadataEndpoint with the Sec-FedCM-CSRF header but without the Identity Provider's cookies. This request MUST NOT follow HTTP redirects and instead return null if there is any error. See also § 5.3 Client Metadata.

  3. Return clientMetadata.

To select an account given an accountsList:
  1. Assert accountsList’s size is greater than 1.

  2. Display an account chooser displaying the options from accountsList.

  3. Let account be the id of the account that the user manually selects from the accounts chooser, or null if no account is selected.

  4. Return account

To sign-in the user with a given an AccountState accountState:
  1. Assert that accountState’s registration state is registered

  2. Change accountState’s allows logout from false to true.

To create tokens given an AccountState accountState, a USVString accountId, and an IdentityProvider provider:
  1. Assert accountState’s registration state is registered.

  2. Assert accountState’s allows logout is true.

  3. Let request be a new object.

    1. Set request["account_id"] to accountId.

    2. Set request["client_id"] to provider’s clientId.

    3. Set request["nonce"] to provider’s nonce.

  4. Let tokens be the result of making a POST request described in § 5.4 ID Token.

  5. Return tokens["token"].

The fetch the manifest algorithm accepts an IdentityProvider provider and returns a Manifest object:
  1. In parallel, perform the following two steps:

    1. Let manifestInSet be the result of running check the root manifest, passing provider.

    2. Let manifest be the result of running fetch the internal manifest, passing provider.

  2. If manifestInSet is true, return manifest, otherwise return null.

NOTE: We use a two-tier manifest list in order to prevent the IDP to easily determine the RP that a user is visiting by encoding the information in the manifest path. We solve this issue by requiring a manifest list to be on the root of the IDP. The manifest itself can be anywhere, but it will not be used if the user agent does not find it in the manifest list. This allows the IDP to keep their actual manifest on an arbitary path while allowing the user agent to prevent manifest manipulation to fingerprint. See § 9.3.1 Manifest Fingerprinting.

The check the root manifest accepts an IdentityProvider provider and whether the manifest is included in the manifest list:

  1. Let url be provider’s configURL.

  2. Let rootUrl be a new URL.

  3. Set rootUrl’s scheme to url’s scheme.

  4. Set rootUrl’s host to url’s host's registrable domain.

  5. Set rootUrl’s path to ".well-known/web-identity".

  6. Let request be a new request whose url is rootUrl and redirect mode set to "error". TODO: what other fields need to be set?

  7. Fetch request with processResponseConsumeBody set to the following steps given a response response:

    1. If response is a network error or its status is not an ok status, return false.

    2. If response’s Content-Type Metadata is not a JSON MIME Type, return false.

    3. Let json be the result of parse JSON bytes to an Infra value passing response’s body.

    4. If json is a parsing exception, or if json is not an ordered map, return false.

    5. If json["provider_urls"] does not exist, or if it is not a list, return false.

    6. If the size of json["provider_urls"] is greater than 1, return false. TODO: determine the right value, probably greater than 1.

    7. If json["provider_urls"][0] is not a string, return false.

    8. Return true if json["provider_urls"][0] is equal to provider’s configURL, otherwise return false.

The fetch the internal manifest algorithm accepts an IdentityProvider provider and returns a Manifest:

  1. Run a Content Security Policy Level 3 check with a connect-src directive on the URL passed as provider’s configURL and return if the check fails.

  2. Return the result of fetching the provider’s configURL and parsing it into a Manifest. TODO: specify how the fetching and the parsing works. The fetch MUST be done with the Sec-FedCM-CSRF header but without the Identity Provider's cookies. This request MUST NOT follow HTTP redirects and instead throw an error if there are any.

7.4.1. IDP Sign-out

In enterprise scenarios, it is common for the user to want to clear all of their existing sessions in all of the Relying Partys they are logged into.

It does so by being navigated to their Identity Provider who initiates what’s called a Front-Channel Logout.

The browser exposes an API that takes the list of Relying Partys that the Identity Provider wants to initiate the logout which are loaded in parallel with cookies.

Each Relying Party endpoint is responsible for clearing its local state (e.g. clearing cookies).

After the completion of this API, the user’s session is cleared and will go through an § 1.1.2.2 Explicit Sign-in upon return.