FedCM updates: IdP Sign-In Status API, Login Hint, and more

Chrome 116 ships FedCM capabilities such as Login Hint API, User Info API, and RP Context API, and starts an origin trial for IdP Sign-In Status API.

In Chrome 116, Chrome is shipping the following three new Federated Credential Management (FedCM) features:

  • Login Hint API: Specify a preferred user account to be signed in.
  • User Info API: Fetch the information of the returning user so that the identity provider (IdP) can render a personalized sign-in button within an iframe.
  • RP Context API: Use a title different from 'Sign in' in the FedCM dialog.

Additionally, Chrome is starting an origin trial for the IdP Sign-In Status API. The IdP Sign-in Status API is a requirement and will be a breaking change when it's shipped. If you have an existing implementation of FedCM, make sure to participate in the origin trial.

Login Hint API

When FedCM is invoked, the browser shows the signed-in account from the specified identity provider (IdP). When the IdP supports multiple accounts, it lists all signed-in accounts.

A FedCM dialog showing multiple user accounts.
A FedCM dialog showing multiple user accounts

After the user signs in, sometimes the relying party (RP) asks the user to reauthenticate. But the user may not be sure which account they've been using. If the RP can specify which account to sign in with, it would be easier for the user to pick an account. Login hint is shipping in Chrome 116 and with it, the RP can narrow the list down to one.

This extension adds an array of login_hints in the accounts list endpoint response from the IdP, with all possible filter types that the IdP supports. For example, the accounts response could look like this when an IdP supports filtering by email and id:

{
  "accounts": [{
    "id": "demo1",
    "email": "demo1@example.com",
    "name": "John Doe",
    "login_hints": ["demo1", "demo1@example.com"],
    ...
  }, {
    "id": "demo2",
    "email": "demo2@example.com",
    "name": "Jane Doe",
    "login_hints": ["demo2", "demo2@example.com"],
    ...
  }, ...]
}

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

return await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: "https://idp.example/manifest.json",
      clientId: "123",
      nonce: nonce,
      loginHint : "demo1@example.com"
    }]
  }
});

User Info API

Sign-in buttons decorated with the IdP's logo that let users sign in with identity federation is now common. However, decorating the button using the user's profile icon and their information is even more intuitive to sign in with, especially when a user has signed up on this website with the IdP before.

Sign-in with Google button.
Sign-in with Google button
Personalized Sign-in with Google button.
Personalized Sign-in with Google button

The challenge is, since the personalized button depends on the third-party cookies on the IdP domain within an iframe to identify the signed-in user to render the button, it won't available once third-party cookies are deprecated.

User Info API, shipping in Chrome 116, provides a way for the IdP to obtain the information of the returning user from the server without depending on the third-party cookies.

The API is expected to be called by the IdP from within an iframe embedded on the RP website so that it can retrieve the user information and render a personalized button as if it's a part of the RP surface. With the API call, the browser makes a request to the accounts list endpoint, then returns an array of user information if:

  • The user has signed in to the RP with the IdP via FedCM in the past on the same browser instance and the data hasn't been cleared.
  • The user is signed in to the IdP on the same browser instance.
// Iframe displaying a page from the https://idp.example origin
const user_info = await IdentityProvider.getUserInfo({
    configUrl: "https://idp.example/fedcm.json",
    clientId: "client1234"
});

// IdentityProvider.getUserInfo returns an array of user information.
if (user_info.length > 0) {
  // Chrome puts returning accounts first, so the first account received is guaranteed to be a returning account.
  const name = user_info[0].name;
  const given_name = user_info[0].given_name;
  const display_name = given_name ? given_name : name;
  const picture = user_info[0].picture;
  const email = user_info[0].email;
  // Renders the personalized sign-in button with the information above.
}

Note that to allow calling IdentityProvider.getUserInfo() from within an iframe that is the same origin as the IdP, the embedding HTML must explicitly allow it with the identity-credentials-get permissions policy.

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

You can see it in action at https://fedcm-rp-demo.glitch.me/button.

RP Context API

RP Context API, shipping in Chrome 116, allows an RP to modify the string in the FedCM dialog UI so that it can accommodate predefined authentication contexts. See the following screenshots for different options:

FedCM dialog rendered with
FedCM dialog rendered with "Sign in to ****". This is the default option if RP Context is not specified.
FedCM dialog rendered with
FedCM dialog rendered with "Sign up to ****"
FedCM dialog rendered with
FedCM dialog rendered with "Continue to ****"
FedCM dialog rendered with
FedCM dialog rendered with "Use ****"

Usage is simple; provide identity.context property one of "signin" (default), "signup", "use" or "continue".

const credential = await navigator.credentials.get({
  identity: {
    // "signin" is the default, "signup", "use" and "continue" 
    // can also be used
    context: "signup", 
    providers: [{
      configURL: "https://idp.example/fedcm.json",
      clientId: "1234",
    }],
  }
});

IdP Sign-In Status API origin trial

Chrome starts an IdP Sign-In Status API origin trial on desktop from Chrome 116, followed by Android Chrome later. Origin trials give you access to a new or experimental feature to build functionality your users can try out for a limited time before the feature is made available to everyone.

IdP Sign-In Status API is a mechanism where an IdP informs the browser of the user's sign-in status on the IdP. With this API, the browser can reduce unnecessary requests to the IdP and mitigate potential timing attacks.

Inform the browser of the user's sign-in status

IdPs can signal the user's sign-in status to the browser by sending an HTTP header or by calling a JavaScript API, when the user is signed in on the IdP, or when the user is signed out from all their IdP accounts. The browser records the status as one of the following: "sign-in", "sign-out", or "unknown" (default).

To signal that the user is signed in, send an IdP-SignIn-Status: action=signin HTTP header in a top-level navigation or a same-origin subresource request:

IdP-SignIn-Status: action=signin

Alternatively, call the JavaScript API IdentityProvider.login() from the IdP origin:

IdentityProvider.login()

These will record the user's sign-in status as "sign-in". When the user's sign-in status is set to "sign-in", the PR calling FedCM makes requests to the IdP's accounts list endpoint and displays available accounts to the user in the FedCM dialog.

To signal that the user is signed out from all their accounts, send the IdP-SignIn-Status: action=signout-all HTTP header in a top-level navigation or a same-origin subresource request:

IdP-SignIn-Status: action=signout-all

Alternatively, call the JavaScript API IdentityProvider.logout() from the IdP origin:

IdentityProvider.logout()

These will record the user's sign-in status as "sign-out". When the user's sign-in status is "sign-out", calling the FedCM silently fails without making a request to the IdP's accounts list endpoint.

By default, the IdP sign-in status is set to "unknown". This status is used before the IdP sends a signal using the IdP Sign-In Status API. We introduce this status for better transition because a user may have already signed in to the IdP when we ship this API and the IdP may not have a chance to signal this to the browser by the time FedCM is first invoked. In this case, we make a request to the IdP's accounts list endpoint and update the status based on the response from the accounts list endpoint:

  • If the endpoint returns a list of active accounts, update the status to "sign-in" and open the FedCM dialog to show those accounts.
  • If the endpoint returns no accounts, update the status to "sign-out" and fail the FedCM call.

What if the user session expires? Let the user sign in through a dynamic sign-in flow

Even though the IdP continues to inform the browser of the user's sign-in status, it could be out of sync, such as when the session expires. The browser tries to send a credentialed request to the accounts list endpoint when the sign-in status is "sign-in", but the server rejects it because the session is no longer available. In such a scenario, the browser can dynamically let the user sign in to the IdP through a popup window.

The FedCM dialog will display a message, as shown in the following image:

A FedCM dialog suggesting to sign in to the IdP.
A FedCM dialog suggesting to sign in to the IdP.

By clicking on the Continue button, the browser opens a popup window sending the user to the IdP's sign-in page.

A popup window shown after clicking on the sign in to the IdP button.
A popup window shown after clicking on the sign in to the IdP button.

The sign-in page URL (which must be the IdP's origin) can be specified with signin_url as part of the IdP config file.

{
  "accounts_endpoint": "/auth/accounts",
  "client_metadata_endpoint": "/auth/metadata",
  "id_assertion_endpoint": "/auth/idtokens",
  "signin_url": "/signin"
  }
}

The popup window is a regular browser window that uses first-party cookies. Whatever happens within the content window is up to the IdP, but no window handles are available to make a cross-origin communication request to the RP page. After the user is signed in, the IdP should:

  • Send the IdP-SignIn-Status: action=signin header or call the IdentityProvider.login() API to inform the browser that the user has been signed in.
  • Call IdentityProvider.close() to close itself (the popup window).
// User is signed in...
// Don't forget feature detection.
if (IdentityProvider) {
  // Signal to the browser that the user has signed in.
  IdentityProvider.close();
}
A user signs into an RP after signing in to the IdP using FedCM

You can try the IdP Sign-In Status API behavior in our demo. The session expires in three minutes after you sign in to the demo IdP. Then you can observe the sign-in to the IdP through the popup window behavior.

Participate in the origin trial

You can try IdP Sign-In Status API locally by turning on a Chrome
flag
chrome://flags#fedcm-idp-signin-status-api on
Chrome 116 or later.

You can also enable the IdP Sign-In Status API by registering an origin trial twice:

Origin trials allow you to try new features and give feedback on their usability, practicality, and effectiveness to the web standards community. For more information, check out the Origin Trials Guide for Web Developers.

The IdP Sign-In Status API origin trial is available from Chrome 116 through Chrome 119.

Register an origin trial for the IdP

  1. Go to the origin trial registration page.
  2. Click the Register button and fill out the form to request a token.
  3. Enter the IdP's origin as Web Origin.
  4. Click Submit.
  5. Add an origin-trial <meta> tag to the head of the pages that use IdentityProvider.close(). For example, this may look something like:
    <meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">.

Register a third-party origin trial for the RP

  1. Go to the origin trial registration page.
  2. Click the Register button and fill out the form to request a token.
  3. Enter the IdP's origin as Web Origin.
  4. Check Third-party matching to inject the token with JavaScript on other origins.
  5. Click Submit.
  6. Embed the issued token on a third-party website.

To embed the token on a third-party website, add the following code to your JavaScript library or SDK served from the IdP's origin.

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

Replace TOKEN_GOES_HERE with your own token.

Engage and share feedback

If you have feedback or encounter any issues during testing, you can share them at crbug.com.

Photo by Dan Cristian Pădureț on Unsplash