Websites may have “Sign in with X” buttons on their page to support federation with an identity provider (IDP). When an end user visits a website (Relying Party, or RP), a personalized button gives them a quick indication of their IDP account status (e.g. name, picture etc.) that is recognizable by users. It could also potentially prevent unnecessary creation of duplicate accounts. See example below for existing personalized buttons on the web.
Currently, personalized buttons are rendered as IDP owned cross-origin iframes on the RP site and have dependency on third-party cookies.
This proposal introduces a new way to implement personalized buttons with the FedCM API for users who have used FedCM to sign in to the RP with the IDP in the past. i.e. it's out of scope if a user never used FedCM on the {RP, IDP} pair in the browser.
Since the button is rendered inside a cross-origin iframe, a permissions policy is required to use FedCM for it. e.g. the top frame needs to specify the existing identity-credentials-get Permissions Policy for the button iframe. In addition, a new API is exposed for the IDP owned iframe to retrieve user information.
Note: to prevent abuse, we only support showing personalized buttons for returning users. i.e. if a user visits an RP with a “Sign in to IDP” button but they never created an account on the RP with the IDP using FedCM API, the user won’t see a personalized button because the browser will not share the user info with the IDP owned iframe.
New Flow Overview
The existing FedCM API for authentication is targeted at all types of users regardless whether they have created a federated account with FedCM before. The browser needs to ask for user permission explicitly before resolving the promise and handing over the token to the API caller.
Since “Personalized button” is targeted only at returning users who have granted permission on the FedCM UI before, i.e. the user must have clicked the “Continue as” button to use a federated account on the RP with their IDP before, under certain circumstances (see below) the browser is allowed to share some user info (e.g. name, picture, email) that is fetched from an IDP with the IDP owned iframe without sacrificing privacy or security. We propose to extend the existing FedCM API to achieve this goal. Below is a flowchart with the high level algorithm.
There are a couple of key checkpoints in the flow:
Request Type
This is to trigger different flows. Specified by API caller (see API Options below for details).
Provider list size
The personalized button request MUST be triggered from an IDP owned iframe, therefore only 1 IDP is allowed per API call
iframe origin
This is to make sure that the destination of the user information is the IDP itself rather than any arbitrary party.
Note that technically speaking the IDP iframe can share the information with its embedder or even embeddees. Given that the feature is for users who have granted permission to allow RP-IDP communication in the past, the potential abuse is impractical.
Permission granted in the past: a user has signed in to the RP with the IDP using FedCM
This is to mitigate the invisible tracking problem for new users who never grant permission to allow the RP-IDP communication before.
Sign in with IDP
This is to further mitigate the invisible tracking problem. If a user is not signed in with an IDP, there’s no reason to continue with network requests because no account will be returned.
Note that the IdpSigninStatus API to obtain the IDP sign-in bit is not launched yet
IDP claimed new user / returning user
While we should purely depend on the browser stored permission grant bit to determine if the user IS a returning user, we can trust IDP if they claim that the user is NOT a returning user. This could happen when a user revokes their account on RP from the IDP side out-of-band so the browser storage is obsolete.
Browser observed new user / returning user
This is the key of the proposal because we only support personalized buttons if a user has granted permission to allow RP-IDP communication in the past. If an {account, RP, IDP} tuple is found, it means that the user is a returning user and we can share their information back to the IDP iframe.
Multiple accounts with the same IDP
It’s possible that a user has multiple active sessions with the same IDP in the same browser profile. If {account1, RP, IDP} is found in browser storage but {account2, RP, IDP} is not, the browser can resolve the promise with both accounts info because:
the feature is post user permission so RP and IDP can communicate out-of-band already
the multiple accounts are using the same IDP cookie and returned from the same accounts request. i.e. IDP knows about account2 just visited RP regardless.
The browser should order the account list to move returning users to the front
Notes
If a user has explicitly signed out from the RP, the browser should still treat them as a returning user because they have granted permission in the past. In addition, the browser cannot really know when this happens.
Currently the browser determines whether a user is a returning user or not by checking a special bit stored in the browser which is set to true when the user signs up with FedCM in the same browser and reset to false when the user clears Browsing history etc.. To expand on the “special bit”:
if the user signed in to RP with FedCM in a top frame, we store {top_orign, idp_origin} and will check that bit upon personalized button request.
if the user signed in to RP with FedCM in a cross-origin iframe, we store {top_origin, iframe_origin, idp_origin}. The personalized button iframe should be embedded in the same iframe so we can check {top_origin, iframe_origin, idp_origin} upon the personalized button request.
if the personalized button iframe is NOT embedded in the same iframe, e.g. it’s embedded in the top frame, the button won’t be personalized because the browser cannot determine whether the user has granted permission or not.
API options
The IDP iframe needs to indicate their intention to use FedCM for personalized buttons instead of tokens. This can be achieved by the options below.
Static getIdentityUserInfo in IdentityCredential
const user_info = await IdentityProvider.getUserInfo({
configUrl: "https://idp.example/fedcm.json",
clientId: "client1234"
});
if (user_info.length > 0) {
// It's up to the IDP regarding how to display the returned accounts. Accounts are sorted based on RP registration status.
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;
}
Pros
Provides a dedicated API for a specific use case
Cons
Need to make IdentityProvider web exposed since it’s not currently exposed
Considered alternatives
Alternative 1: Static getIdentityUserInfo in IdentityCredential
const user_info = await IdentityCredential.getUserInfo({
configUrl: "https://idp.example/fedcm.json",
clientId: "client1234"
});
// same as above
Pros
Provides a dedicated API for a specific use case
Cons
While personalized button only allows single IDP in the API, the “personalized button intention” is closer to IdentityProvider than to IdentityCredential
Easy to extend from ergonomics’ perspective. e.g. if we support other use cases using the same navigator.credentials.get call in the future, we can add new requestTypes. e.g. “revocation” to revoke an account on the IDP side.
Cons
Overloading navigator.credentials.get with different use cases may be suboptimal from API design’s perspective
Privacy Consideration
The major difference between the existing token flow and the personalized button flow is that the latter does not require explicit user permission at API invocation time. However, an explicit user permission to allow the RP-IDP communication MUST be granted in the browser in the past (e.g. the browser stores such permission locally after a previous FedCM grant). i.e. the new feature only works “post permission”. As shown in the demo, a user won’t see their personal information on a button before they use FedCM to sign in to the RP with the IDP.
One caveat on the permission: while it's up to the user agents to decide whether to revoke it upon clearing browsing history or whether to sync it across devices, it should not be revoked when the user signs out from the RP or IDP because the user is not explicitly revoking the granted permission in that case. We are planning to ship a Revocation API to allow users to disconnect RP and IDP and the permission should be revoked there.
It’s worth noting that there’s a potential invisible tracking problem in the FedCM API. The way we mitigate the problem is to make sure that all accounts fetches end up with some browser UI to make the tracking visible to users. Unlike the token flow which is targeted at all users, the personalized button flow only works for returning users. i.e. an explicit user permission to allow RP-IDP communication has been granted in the browser in the past. Thus, bad actors can track user visits on an RP already. e.g. during the last time the user logged in with FedCM, RP and IDP could have already exchanged an identifier such that the RP could just make a fetch to the IDP and reveal relevant information to IDP anyway. Therefore, if the accounts request fails silently or the IDP iframe chooses to display nothing, there’s no new privacy risk introduced.
Security Consideration
The personalized button flow is only supported when the API is invoked from an IDP owned iframe to avoid leaking user information to an arbitrary party. In addition, we limit the size of the IDP list to 1 to avoid leaking user information to unrelated IDPs. In addition, the user permission granted in the past to gate the personalized button flow does not get synced across devices so that there’s no security risk there either.
It’s worth noting that technically speaking the IDP iframe can share the information with its embedder or even embeddees. Given that the feature is for users who have granted permission to allow RP-IDP communication in the past, the potential abuse is impractical.
Notes about why we propose a new userInfo flow: compared to the existing token flow, it
must be performed with some restrictions (e.g. same-origin with IDP, returning user etc.)
does not need user interaction
returns “less user information” (only preset fields)
the token can encode any data the IDP might want to give to the RP
The new flow provides a dedicated high level API for IDPs. However, from security’s point of view, it does not really ensure anything more than using the userInfo flow with the same restrictions because IDP can still pass in extra information in the preset fields so “less user information” cannot really be enforced by the browser.
Motivation
Websites may have “Sign in with X” buttons on their page to support federation with an identity provider (IDP). When an end user visits a website (Relying Party, or RP), a personalized button gives them a quick indication of their IDP account status (e.g. name, picture etc.) that is recognizable by users. It could also potentially prevent unnecessary creation of duplicate accounts. See example below for existing personalized buttons on the web.
Currently, personalized buttons are rendered as IDP owned cross-origin iframes on the RP site and have dependency on third-party cookies.
This proposal introduces a new way to implement personalized buttons with the FedCM API for users who have used FedCM to sign in to the RP with the IDP in the past. i.e. it's out of scope if a user never used FedCM on the {RP, IDP} pair in the browser.
See a proof of concept demo below:
https://user-images.githubusercontent.com/23404313/205805729-5713eba4-6d2d-42c0-a187-e1ea0b223144.mov
Proposal
Since the button is rendered inside a cross-origin iframe, a permissions policy is required to use FedCM for it. e.g. the top frame needs to specify the existing identity-credentials-get Permissions Policy for the button iframe. In addition, a new API is exposed for the IDP owned iframe to retrieve user information.
Note: to prevent abuse, we only support showing personalized buttons for returning users. i.e. if a user visits an RP with a “Sign in to IDP” button but they never created an account on the RP with the IDP using FedCM API, the user won’t see a personalized button because the browser will not share the user info with the IDP owned iframe.
New Flow Overview
The existing FedCM API for authentication is targeted at all types of users regardless whether they have created a federated account with FedCM before. The browser needs to ask for user permission explicitly before resolving the promise and handing over the token to the API caller.
Since “Personalized button” is targeted only at returning users who have granted permission on the FedCM UI before, i.e. the user must have clicked the “Continue as” button to use a federated account on the RP with their IDP before, under certain circumstances (see below) the browser is allowed to share some user info (e.g. name, picture, email) that is fetched from an IDP with the IDP owned iframe without sacrificing privacy or security. We propose to extend the existing FedCM API to achieve this goal. Below is a flowchart with the high level algorithm.
There are a couple of key checkpoints in the flow:
Notes
API options
The IDP iframe needs to indicate their intention to use FedCM for personalized buttons instead of tokens. This can be achieved by the options below.
Static getIdentityUserInfo in IdentityCredential
Considered alternatives
Alternative 1: Static getIdentityUserInfo in IdentityCredential
Alternative 2: RequestType in IdentityProvider
Privacy Consideration
The major difference between the existing token flow and the personalized button flow is that the latter does not require explicit user permission at API invocation time. However, an explicit user permission to allow the RP-IDP communication MUST be granted in the browser in the past (e.g. the browser stores such permission locally after a previous FedCM grant). i.e. the new feature only works “post permission”. As shown in the demo, a user won’t see their personal information on a button before they use FedCM to sign in to the RP with the IDP.
One caveat on the permission: while it's up to the user agents to decide whether to revoke it upon clearing browsing history or whether to sync it across devices, it should not be revoked when the user signs out from the RP or IDP because the user is not explicitly revoking the granted permission in that case. We are planning to ship a Revocation API to allow users to disconnect RP and IDP and the permission should be revoked there.
It’s worth noting that there’s a potential invisible tracking problem in the FedCM API. The way we mitigate the problem is to make sure that all accounts fetches end up with some browser UI to make the tracking visible to users. Unlike the token flow which is targeted at all users, the personalized button flow only works for returning users. i.e. an explicit user permission to allow RP-IDP communication has been granted in the browser in the past. Thus, bad actors can track user visits on an RP already. e.g. during the last time the user logged in with FedCM, RP and IDP could have already exchanged an identifier such that the RP could just make a fetch to the IDP and reveal relevant information to IDP anyway. Therefore, if the accounts request fails silently or the IDP iframe chooses to display nothing, there’s no new privacy risk introduced.
Security Consideration
The personalized button flow is only supported when the API is invoked from an IDP owned iframe to avoid leaking user information to an arbitrary party. In addition, we limit the size of the IDP list to 1 to avoid leaking user information to unrelated IDPs. In addition, the user permission granted in the past to gate the personalized button flow does not get synced across devices so that there’s no security risk there either.
It’s worth noting that technically speaking the IDP iframe can share the information with its embedder or even embeddees. Given that the feature is for users who have granted permission to allow RP-IDP communication in the past, the potential abuse is impractical.
Notes about why we propose a new
userInfo
flow: compared to the existingtoken
flow, itThe new flow provides a dedicated high level API for IDPs. However, from security’s point of view, it does not really ensure anything more than using the
userInfo
flow with the same restrictions because IDP can still pass in extra information in the preset fields so “less user information” cannot really be enforced by the browser.