Federated Credential Management API: developer guide

Learn how to use FedCM for for privacy-preserving identity federation.

Published on Updated on

FedCM (Federated Credential Management) is a privacy-preserving approach to federated identity services (such as "Sign in with...") where users can log into sites without sharing their personal information with the identity service or the site.

To learn more about FedCM use cases, user flows, and API roadmap check out the introduction to FedCM API.

FedCM development environment

You need a secure context (HTTPS or localhost) both on the IdP and RP in Chrome to use the FedCM.

Debug code on Chrome on Android

Set up and run a server locally to debug your FedCM code. You can access this server in Chrome on an Android device connected using a USB cable with port forwarding.

You can use DevTools on desktop to debug Chrome on Android by following the instructions at Remote debug Android devices.

Block third-party cookies on Chrome

Simulate third-party cookie phase-out by configuring Chrome to block them
Simulate third-party cookie phase-out by configuring Chrome to block them

You can test how FedCM works without third-party cookies on Chrome before it's actually enforced.

To block third-party cookies, use Incognito mode, or choose "Block third-party cookies" in your desktop settings at chrome://settings/cookies or on mobile by navigating to Settings > Site settings > Cookies.

Caution

FedCM is temperarily disabled when third-party cookies are blocked. Starting from Chrome 110, you can force enable it with the Chrome flag: chrome://flags/#fedcm-without-third-party-cookies.

Using the FedCM API

You integrate with FedCM by creating a well-known file, config file and endpoints for accounts list, assertion issuance and optionally client metadata.

From there, FedCM exposes JavaScript APIs that RPs can use to sign in with the IdP.

Create a well-known file

To prevent trackers from abusing the API, a well-known file must be served from /.well-known/web-identity of eTLD+1 of the IdP.

For example, if the IdP endpoints are served under https://accounts.idp.example/, they must serve a well-known file at https://idp.example/.well-known/web-identity as well as an IdP config file. Here's an example well-known file content:

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

The JSON file must contain the provider_urls property with an array of IdP config file URLs that can be specified as a path part of configURL in navigator.credentials.get by RPs. The number of URL strings in the array is limited to one, but this may change with your feedback in the future.

Create an IdP config file and endpoints

The IdP config file provides a list of required endpoints for the browser. IdPs will host this config file and the required endpoints. All JSON response must be served with application/json content type.

The config file's URL is determined by the values provided to the navigator.credentials.get call executed on an RP.

const credential = await navigator.credentials.get({
identity: {
context: 'signup',
providers: [{
configURL: 'https://accounts.idp.example/config.json',
clientId: '********',
nonce: '******',
loginHint: 'demo1@example.com'
}]
}
});
const { token } = credential;

Specify a full URL of the IdP config file location as a configURL. When navigator.credentials.get() is called on the RP, the browser fetches the config file with a GET request without the Origin header or the Referer header. The request doesn't have cookies and doesn't follow redirects. This effectively prevents the IdP from learning who made the request and which RP is attempting to connect. For example:

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

All requests sent from the browser via FedCM include a Sec-Fetch-Dest: webidentity header to prevent CSRF attacks. All IdP endpoints must confirm this header is included.

The browser expects a JSON response from the IdP which includes the following properties:

PropertyDescription
accounts_endpoint (required)URL for the accounts list endpoint.
client_metadata_endpoint (optional)URL for the client metadata endpoint.
id_assertion_endpoint (required)URL for the ID assertion endpoint.
branding (optional)Object which contains various branding options.
branding.background_color (optional)Branding option which sets the background color of the "Continue as..." button. Use the relevant CSS syntax, namely hex-color, hsl(), rgb(), or named-color.
branding.color (optional)Branding option which sets the text color of the "Continue as..." button. Use the relevant CSS syntax, namely hex-color, hsl(), rgb(), or named-color.
branding.icons (optional)Branding option which sets the icon object, displayed in the sign-in dialog. The icon object is an array with two parameters:
  • url (required): URL of the icon image. This does not support SVG images.
  • size (optional): icon dimensions, assumed by the application to be square and single resolution. This number must be greater than or equal to 25.

RP could modify the string in the FedCM dialog UI via identity.context value for navigator.credentials.get() to accommodate predefined authentication contexts. Optional property can be one of "signin" (default), "signup", "use" or "continue".

How branding is applied to the FedCM dialog

Here's an example response body from the IdP:

{
"accounts_endpoint": "/accounts.php",
"client_metadata_endpoint": "/client_metadata.php",
"id_assertion_endpoint": "/assertion.php",
"branding": {
"background_color": "green",
"color": "#FFEEAA",
"icons": [{
"url": "https://idp.example/icon.ico",
"size": 25
}]
}
}

Once the browser fetches the config file, it sends subsequent requests to the IdP endpoints:

IdP endpoints
Caution

If the RP deploys Content Security Policy (CSP) on the page FedCM is called and enforce connect-src directive, they must explicitly allow endpoints described in the config file.

Accounts list endpoint

The IdP's accounts list endpoint returns a list of accounts that the user is currently signed in on the IdP. If the IdP supports multiple accounts, this endpoint will return all signed in accounts.

The browser sends a GET request with cookies, but without a client_id parameter, the Origin header or the Referer header. This effectively prevents the IdP from learning which RP the user is trying to sign in to. For example:

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

The browser expects a JSON response that includes an accounts property with an array of account information with following properties:

PropertyDescription
id (required)Unique ID of the user.
name (required)Given and family name of the user.
email (required)Email address of the user.
given_name (optional)Given name of the user.
picture (optional)URL of the user avatar image.
approved_clients (optional)An array of RP client IDs which the user has registered with.

Example response body:

{
"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"],
"login_hints": ["demo1", "demo1@example.com"],
}, {
"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", "demo2@example.com"],
}]
}

If the user is not signed in, respond with HTTP 401 (Unauthorized).

The returned accounts list is consumed by the browser and will not be available to the RP.

By passing login_hints in the accounts list, the RP can invoke navigator.credentials.get() with the loginHint property to selectively show the specified account.

Client metadata endpoint

The IdP's client metadata endpoint returns the relying party's metadata such as the RP's privacy policy and terms of service. RPs should provide links to their privacy policy and terms of service to the IdP in advance. These links are displayed in the sign-in dialog when the user hasn't registered on the RP with the IdP yet.

The browser sends a GET request using the client_id navigator.credentials.get without cookies. For example:

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

The properties for the client metadata endpoint include:

PropertyDescription
privacy_policy_url (optional)RP privacy policy URL.
terms_of_service_url (optional)RP terms of service URL.

The browser expects a JSON response from the endpoint:

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

The returned client metadata is consumed by the browser and will not be available to the RP.

ID assertion endpoint

The IdP's ID assertion endpoint returns an assertion for their signed-in user. When the user signs in to an RP website using navigator.credentials.get() call, the browser sends a POST request with cookies and a content type of application/x-www-form-urlencoded to this endpoint with the following information:

PropertyDescription
client_id (required)The RP's client identifier.
account_id (required)The unique ID of the signing in user.
nonce (optional)The request nonce, provided by the RP.
disclosure_text_shownResults in a string of "true" or "false" (rather than a boolean). The result is "false" if the disclosure text was not shown. This happens when the RP's client ID was included in the approved_clients property list of the response from the accounts list endpoint or if the browser has observed a sign-up moment in the past in the absence of approved_clients.

Example HTTP header:

POST /assertion.php HTTP/1.1
Host: accounts.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=Ct60bD&disclosure_text_shown=true

On the server, the IdP should confirm that:

  1. The claimed account ID matches the ID for the account that is already signed in.
  2. The Origin header matches the origin the RP, registered in advance for the given client ID.
Warning

Since the domain verification on OAuth or OpenID Connect relies on a browser redirect, it's critical in FedCM that the IdP server checks an Origin header value matches the RP's registered origin.

The browser expects a JSON response that includes the following property:

PropertyDescription
token (required)A token is a string that contains claims about the authentication.
{
"token": "***********"
}

The returned token is passed to the RP by the browser, so that the RP can validate the authentication.

Sign in to the relying party with the identity provider

Once the IdP's configuration and endpoints are available, RPs can call navigator.credentials.get() to request allowing users to sign in to the RP with the IdP.

Before calling the API, you need to confirm that [FedCM is available on the user's browser]. To check if FedCM is available, wrap this code around your FedCM implementation:

if ('IdentityCredential' in window) {
// If the feature is available, take action
}

To request allowing users to sign in to the IdP from the RP, do the following, for example:

const credential = await navigator.credentials.get({
identity: {
providers: [{
configURL: 'https://accounts.idp.example/config.json',
clientId: '********',
nonce: '******'
}]
}
});
const { token } = credential;

The providers property takes an array of IdentityProvider objects that have the following properties:

PropertyDescription
configURL (required)A full path of the IdP config file.
clientId (required)The RP's client identifier, issued by the IdP.
nonce (optional)A random string to ensure the response is issued for this specific request. Prevents replay attacks.

The browser handles sign-up and sign-in use cases differently depending on the existence of approved_clients in the response from the accounts list endpoint. The browser will not display a disclosure text "To continue with ...." if the user has already signed up to the RP.

The sign-up state is determined based on whether the following conditions are fulfilled or not:

  • If approved_clients includes the RP's clientId.
  • If the browser remembers that the user has already signed up to the RP.
A user signs into an RP using FedCM

When the RP calls navigator.credentials.get(), the following activities take place:

  1. The browser sends requests and fetches several documents:
    1. The well-known file and an IdP config file which declare endpoints.
    2. An accounts list.
    3. Optional: URLs for the RP's privacy policy and terms of service, retrieved from the client metadata endpoint.
  2. The browser displays the list of accounts that the user can use to sign-in, as well as the terms of service and privacy policy if available.
  3. Once the user chooses an account to sign in with, a request to the ID assertion endpoint is sent to the IdP to retrieve a token.
  4. The RP can validate the token to authenticate the user.
login API call
Caution

FedCM is designed to not inform the RP of the user's IdP sign-in state until the user explicitly confirms to Continue as and signs in. This means RPs aren't informed of connection to the FedCM API if: the user isn't signed into the IdP, the accounts list endpoint returns an empty list, or the endpoint returns an error.

RPs are expected to support browsers which don't support FedCM, therefore users should be able to use an existing, non-FedCM sign-in process. Until third-party cookies are phased out completely, this should remain non-problematic.

Once the token is validated by the RP server, the RP may register the user or let them sign-in and start a new session.

Auto-reauthenticate users after the initial consent

FedCM auto-reauthentication ("auto-reauthn" in short) can let users reauthenticate automatically, when they come back after their initial authentication using FedCM. "The initial authentication" here means the user creates an account or signs into the RP's website by tapping on the "Continue as..." button on FedCM's sign-in dialog for the first time on the same browser instance.

While the explicit user experience makes sense before the user has created the federated account to prevent tracking (which is one of the main goals of FedCM), it is unnecessarily cumbersome after the user has gone through it once: after the user grants permission to allow communication between the RP and the IdP, there's no privacy or security benefit for enforcing another explicit user confirmation for something that they have already previously acknowledged.

With auto-reauthentication, the browser changes its behavior depending on the option you specify for the mediation when calling navigator.credentials.get().

const cred = await navigator.credentials.get({
identity: {
providers: [{
configURL: "https://idp.example/fedcm.json",
clientId: "1234",
}],
},
mediation: 'optional', // this is the default
});

The mediation is a property in the Credential Management API, it behaves in the same way as it does for PasswordCredential and FederatedCredential and it's partially supported by PublicKeyCredential as well. The property accepts the following four values:

  • 'optional'(default): Auto-reauthn if possible, requires a mediation if not. We recommend choosing this option on the sign-in page.
  • 'required': Always requires a mediation to proceed, for example, clicking the "Continue" button on the UI. Choose this option if your users are expected to grant permission explicitly every time they need to be authenticated.
  • 'silent': Auto-reauthn if possible, silently fail without requiring a mediation if not. We recommend choosing this option on the pages other than the dedicated sign-in page but where you want to keep users signed in—for example, an item page on a shipping website or an article page on a news website.
  • 'conditional': Used for WebAuthn and not available for FedCM at the moment.

With this call, auto-reauthn happens under the following conditions:

  • FedCM is available to use. For example, the user has not disabled FedCM either globally or for the RP in the settings.
  • The user used only one account with FedCM API to sign into the website on this browser.
  • The user is signed into the IdP with that account.
  • The auto-reauthn didn't happen within the last 10 minutes.
  • The RP hasn't called navigator.credentials.preventSilentAccess() after the previous sign in.

When the above conditions are met, an attempt to automatically reauthenticate the user starts as soon as the FedCM navigator.credentials.get() is invoked.

A user auto-reauthenticating through FedCM.

Enforce mediation with preventSilentAccess()

Auto-reauthenticating users immediately after they sign out would not make for a very good user experience. That's why FedCM has a 10-minute quiet period after an auto-reauthn to prevent this behavior. This means that auto-reauthn happens at most once in every 10-minutes unless the user signs back in within 10-minutes. The RP should call navigator.credentials.preventSilentAccess() to explicitly request the browser to disable auto-reauthn when a user signs out of the RP explicitly, for example, by clicking a sign-out button.

function signout() {
navigator.credentials.preventSilentAccess();
location.href = '/signout';
}

Users can opt-out of auto-reauthn in settings

Users can opt-out from auto-reauth from the settings menu:

  • On desktop Chrome, go to chrome://password-manager/settings > Sign in automatically.
  • On Android Chrome, open Settings > Password Manager > Tap on a cog at the top right corner > Auto sign-in.

By disabling the toggle, the user can opt-out from auto-reauthn behavior all together. This setting is stored and synchronized across devices, if the user is signed into a Google account on the Chrome instance and synchronization is enabled.

Call FedCM from within a cross-origin iframe

FedCM can be invoked from within a cross-origin iframe using an identity-credentials-get permissions policy, if the parent frame allows it. To do so, append the allow="identity-credentials-get" attribute to the iframe tag as follows:

<iframe src="https://fedcm-cross-origin-iframe.glitch.me" allow="identity-credentials-get"></iframe>

You can see it in action in an example.

Optionally, if the parent frame wants to restrict the origins to call FedCM, send a Permissions-Policy header with a list of allowed origins.

Permissions-Policy: identity-credentials-get=(self "https://fedcm-cross-origin-iframe.glitch.me")

You can learn more about how the Permissions Policy works at Controlling browser features with Permissions Policy.

Updated on Improve article

This site uses cookies to deliver and enhance the quality of its services and to analyze traffic. If you agree, cookies are also used to serve advertising and to personalize the content and advertisements that you see. Learn more about our use of cookies.