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 permission before allowing 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 sign up on the Relying Party with the Identity Provider ?". Upon user agreement an account is created with the Identity Provider and the user has a session initialized on Relying Party .
1.1.2. Sign-in
After a user navigates to a Relying Party in a browser and creates an account by going through their § 1.1.1 Sign-up flow, the user can sign into their account once their session expires.
A 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 already has an account with the Relying Party .
-
the user has logged out of the Relying Party .
The user is then prompted, "Do you want to sign in on the Relying Party with the Identity Provider ?" 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 session s:
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 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 , the user will need to sign in with the Identity Provider first and go through the § 1.1.2 Sign-in flow on the Relying Party .
1.1.4. Revocation
After a user has created an account on 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 account revocation 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 grants permission 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
IDP
s
and
RP
s.
When
it
succeeds,
it
returns
to
the
RP
a
signed
token
which
the
RP
can
use
to
authenticate
the
user.
< 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({ 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
- RP
-
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 - 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 Federated Credential Management API works by the intermediation of cooperating IDP s and RP s.
The § 5 The Identity Provider API and the § 6 The Relying Party API defines a set of HTTP APIs that cooperating IDP s and IDP s 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:
5. The Identity Provider API
This section is non-normative.
The IDP proactively and cooperatively exposes itself as a comformant agent by exposing a series of HTTP endpoints:
-
A § 5.2 Manifest endpoint in an agreed upon location that points to
-
An § 5.3 Accounts List endpoint
-
A § 5.4 Client Metadata endpoint
-
An § 5.5 Identity Assertions endpoint
The
IDP
must also host a file at the ".well-known/web-identity" path of its
registrable domain
that has JSON contents that are convertable to an
IdentityProviderWellKnown
object.
dictionary {
IdentityProviderWellKnown required sequence <USVString >; };
provider_urls
The algorithms used for these endpoints need to integrate with fetch .
5.1. The Well-Known File
NOTE: The browser uses the well-known file to prevent the following attack described here .
The IDP exposes a well-known file in a pre-defined location, specifically at the "web-identity" file at the IDPs 's path ".well-known".
The well-known file is fetched:
(a)
without
cookies, (b)
with
the
Sec-Fetch-Dest
header set to
webidentity
, and (c)
without
a
Referer
header
For example:
GET /well-known/web-identity HTTP / 1.1 Host : idp.example Accept : application/json Sec-Fetch-Dest : webidentity
The file is parsed expecting a Well-Known JSON object.
The Well-Known JSON object has the following properties:
-
provider_urls
(required) -
A list of URLs that points to valid § 5.2 Manifest s.
5.2. Manifest
The config endpoint is an endpoint which serves as a discovery device to other endpoints provided by the IDP .
The config endpoint is fetched:
(a)
without
cookies, (b)
with
the
Sec-Fetch-Dest
header set to
webidentity
, (c)
without
a
Referer
header, and (c)
without
following
HTTP redirects
.
For example:
The response body must be a JSON object that can be
converted
to an
IdentityProviderAPIConfig
without an exception.
dictionary {
IdentityProviderIcon required USVString url ;unsigned long size ; };dictionary {
IdentityProviderBranding USVString background_color ;USVString color ;sequence <IdentityProviderIcon >icons ; };dictionary {
IdentityProviderAPIConfig required USVString accounts_endpoint ;required USVString client_metadata_endpoint ;required USVString id_assertion_endpoint ;IdentityProviderBranding branding ; };
The
IdentityProviderAPIConfig
object’s members have the following semantics:
-
accounts_endpoint
, of type USVString -
A URL that points to an HTTP API that complies with the § 5.3 Accounts List API.
-
client_metadata_endpoint
, of type USVString -
A URL that points to an HTTP API that complies with the § 5.4 Client Metadata API.
-
id_assertion_endpoint
, of type USVString -
A URL that points to an HTTP API that complies with the § 5.5 Identity Assertions API.
-
branding
, of type IdentityProviderBranding -
A set of
IdentityProviderBranding
options.
The
IdentityProviderBranding
enables an
IDP
to express their branding preferences, which may be used by
user agents
to customize the permission 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.
Its members have the following semantics:
-
background_color
, of type USVString -
color
, of type USVString -
icons
, of type sequence< IdentityProviderIcon > -
A list of
IdentityProviderIcon
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
IdentityProviderIcon
has members with the following semantics:
-
url
, of type USVString -
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
, of type unsigned long -
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_assertion_endpoint" : "/assertion.php" , "branding" : { "background_color" : "green" , "color" : "0xFFEEAA" , "icons" : [{ "url" : "https://idp.example/icon.ico" , "size" : 25 }] } }
5.3. 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
the
Sec-Fetch-Dest
header set to
webidentity
, (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-Fetch-Dest : webidentity
The response body must be a JSON object that can be
converted
to an
IdentityProviderAccountList
without an exception.
dictionary {
IdentityProviderAccount required USVString id ;required USVString name ;required USVString USVString given_name ;sequence <USVString >approved_clients ; };dictionary {
IdentityProviderAccountList sequence <IdentityProviderAccount >; };
accounts
Every
IdentityProviderAccount
is expected to have members with the following semantics:
-
id
, of type USVString -
The account unique identifier.
-
name
, of type USVString -
The user’s full name.
-
email
, of type USVString -
The user’s email address.
-
given_name
, of type USVString -
The user’s given name.
-
approved_clients
, of type sequence< USVString > -
A list of RP s (in the form of Client ID s) this account is already registered with. Used in the request permission 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" ] }] }
Clarify the IDP API response when the user is not signed in.
5.4. Client Metadata
The client metadata endpoint provides metadata about RP s.
The client medata endpoint is fetched (a)
without
cookies, (b)
with
the
Sec-Fetch-Dest
header set to
webidentity
, (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-Fetch-Dest : webidentity
The response body must be a JSON object that can be
converted
to an
IdentityProviderClientMetadata
without an exception.
dictionary {
IdentityProviderClientMetadata USVString privacy_policy_url ;USVString terms_of_service_url ; };
The
IdentityProviderClientMetadata
object’s members have the following semantics:
-
privacy_policy_url
, of type USVString -
A link to the RP 's privacy policy .
-
terms_of_service_url
, of type USVString -
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.5. Identity Assertions
The identity assertion endpoint is responsible for minting a new token that contains signed assertions about the user.
The identity assertion 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
the
Sec-Fetch-Dest
header set to
webidentity
, (e)
without
following
HTTP redirects
.
It will also contain the following parameters in the request body
application/x-www-form-urlencoded
:
-
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 permission to sign-up algorithm for new users but not by the sign-in algorithm for returning users.
For example:
POST /fedcm_assertion_endpoint HTTP / 1.1 Host : idp.example Referer : 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
The response body must be a JSON object that can be
converted
to an
IdentityProviderToken
without an exception.
dictionary {
IdentityProviderToken required USVString token ; };
Every
IdentityProviderToken
is expected to have members with the following semantics:
-
token
, of type USVString -
The resulting token .
The content of the token is opaque to the user agent and can contain anything that the Identity Provider would like to pass to the Relying Party to facilitate the login.
NOTE: For Identity Providers , it is worth considering how portable accounts are. Portability is left entirely up to Identity Providers , who can choose between a variety of different mechanisms to accomplish it (e.g. OIDC’s Account Porting ).
For example:
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 IDP s 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 RP s, 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 RP s and IDP s to call and intermediates the exchange of the user’s identity.
The Sign-up and Sign-in APIs are used by the Relying Party s 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 on the RP with the IDP 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 thatlogoutRPs()
has not yet been called on this account after the last successfulIdentityCredential
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
IdentityProviderConfig
s that the
Relying Party
supports and has pre-registered with (i.e. it has a
clientId
).
dictionary {
IdentityCredentialRequestOptions sequence <IdentityProviderConfig >; };
providers
Each
IdentityProviderConfig
represents an
Identity Provider
that the
Relying Party
supports (e.g. that it has a pre-registration agreement with).
dictionary {
IdentityProviderConfig required USVString ;
configURL required USVString ;
clientId USVString ; };
nonce
-
configURL
-
The URL of the configuration file for the identity provider.
-
clientId
-
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 Provider
s.
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 aCredential
abstract operation. -
options
-
This argument is a
CredentialRequestOptions
object whoseidentity
member contains anIdentityCredentialRequestOptions
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 isfalse
if caller is cross-origin.Note: Invocation of this internal method indicates that it was allowed by permissions policy , which is evaluated at the Credential Management Level 1 level. See § 8 Permissions Policy Integration . As such, sameOriginWithAncestors is unused.
NOTE:
The
mediation
flag is currently not used.
The
signal
is used as an abort signal for the requests.
IdentityCredential
's
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
IdentityCredential
(or throws an error to the caller). -
Assert: These steps are running in parallel .
-
Assert: options ["
identity
"]["providers
"] size is 1.Support choosing accounts from multiple Identity Provider s, as described here .
-
Run
setTimeout
passing a task which throws aNetworkError
, after a timeout of 60 seconds.Do not use
setTimeout
directly, as that is not correct. See the relevant issue .Note: the purpose of having a timer here is to avoid leaking the reason causing this method to throw an error. 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 granting permission to share the IDP account information with the RP .
-
Let credential
potentially create IdentityCredentialbe the result of running create an IdentityCredential with provider and globalObject .Note: The globalObject is not currently passed onto the
[[DiscoverFromExternalSource]]
algorithm. See issue . -
If credential
potentially create IdentityCredentialis failure, queue a global task on the DOM manipulation task source to throw a new "TypeErrorNetworkErrorNetworkErrorDOMExceptioncredential . potentially create IdentityCredential.
IdentityProviderConfig
provider
and a
globalObject
, run the following steps. This returns an
IdentityCredential
or failure. -
Assert: These steps are running in parallel .
-
Let
manifest fetch the manifestconfig be the result of running fetch the config file with provider and globalObject . -
If
manifest is null, return null.config is failure, return failure. -
Let accountsList be the result of fetch the accounts list
manifestwith config , provider , and globalObject . -
If accountsList
’s size is 0, return null. If accountsList’s size is 1:-
Let account be accountsList [0].
-
Let accountState be the result of running the compute account state algorithm given provider , account , and globalObject .
-
If accountState ’s
registration state
is unregistered , let permission be the result of running request permission to sign-up algorithm with account , accountState ,manifestconfig , provider , and globalObject . -
Otherwise, show a dialog to request user permission to sign in via account , and set the result in permission .
-
If the user grants permission, run theIf permission , sign-in with accountState .
-
-
Otherwise:
-
Let account be the result of running the select an account from the accountsList .
-
If account
is null, return null.is failure, return failure. -
Let accountState be the result of running the compute account state algorithm given provider and account .
-
If accountState ’s
registration state
is unregistered :-
Let permission be the result of running the request permission to sign-up algorithm with account , accountState ,
manifestconfig , provider , and globalObject . -
Otherwise, run theIf permission , sign-in with accountState .
-
-
Otherwise, sign-in with accountState .
-
-
Wait until the user agent 's dialog is closed.
-
If accountState ’s
registration state
is unregisteredthen return null.then return failure. -
Let
token create tokenscredential be the result of running the fetch an identity assertion algorithm with accountState , account ’sid
, provider , config , andmanifestglobalObject . -
LetReturn credential .
IdentityCredential
USVString
.
stringUrl
, a
globalObject
, and an optional
baseUrl
(default null), run the following steps. This returns a
URL
or failure. -
Let configUrl be null.
-
Set credential ’s tokentokenQueue a global task on the DOM manipulation task source given globalObject to set configUrl to the result of running url parser with stringUrl and baseUrl .Note: We queue a task since the url parser needs to be run within a task, not in parallel .
-
Wait for configUrl to be set.
-
Return
credentialconfigUrl .compute account state
-
Queue a global task on the network task source given globalObject to:
-
Fetch request with processResponseConsumeBody set to processResponseConsumeBody .
-
Note: We queue a task since the fetch needs to be run within a task, not in parallel .
IdentityProviderConfig
provider
and
globalObject
, run the following steps. This returns an
IdentityProviderAccount
IdentityProviderAPIConfig
account
. -
Let configUrl
url parserbe the result of running parse url with provider ’sconfigURL
and globalObject .. Let idpOrigin origin configUrl -
Let rpOrigin this 's origin .If configUrl is failure, return failure. -
Let accountId account ’sRun aidContent Security Policy Level 3.check with a connect-src directive on the URL passed as configUrl . If it fails, return failure. -
If configUrl is not a potentially trustworthy URL , return failure.
-
Let
triple be ( rpOrigin idpOrigin accountId ).rootUrl be a new URL . -
If state machine map [ tripleSet rootUrl] does not exist, set state machine map [ triple’s scheme to configUrl] to a new AccountState’s scheme . -
Let accountState state machine map [ tripleSet rootUrl]. Return accountState . fetch the accounts list IdentityProviderAPIConfig manifest IdentityProviderConfig provider Let accountsUrl computing the manifest URL provider manifest’s host to configUrl[" accounts_endpoint’s host"].'s registrable domain . -
Set rootUrl ’s path to the list «".well-known", "web-identity"».
-
If
accountsUrl is failure, return an empty list.rootUrl is not a potentially trustworthy URL , return failure. -
Let wellKnownRequest be a new request
request with the following properties:as follows:-
url accountsUrlURL -
rootUrl
redirect mode set to "error" -
client
set to null -
null
-
window
set to "no-window" -
"no-window"
-
service-workers mode
set to "none" -
"none"
-
destination
set to "webidentity" -
"webidentity"
- origin
- header list
-
a list containing a single header with name set to
Accept
and value set toapplication/json
-
referrer policy
set to "no-referrer" -
"no-referrer"
-
credentials mode
set to "include" -
"omit"
here .The spec is yet to be updated so that all requests are created with mode set to "unsafe-no-cors". See the relevant pull request for details. -
-
Let
accountsList IdentityProviderAccountList . Note: integrate with Fetch.config be null. -
Fetch requestFetch request with wellKnownRequest , globalObject , and processResponseConsumeBody set to the following steps given a response response :-
Let json be the result of extract the JSON fetch response from response .
-
Convert json to an
IdentityProviderAccountListIdentityProviderWellKnownpotentialAccountsList . Set accountsList potentialAccountsList . Note: integrate with Fetch. Return accountsList . here . computing the manifest URL IdentityProviderConfig provider string manifestString Let configUrl url parser provider ’s configURL . Let manifestUrl url parser manifestStringdiscovery . -
If manifestUrl manifestUrl url parser manifestString configUrl (the base URL). Note: This means the we allow passing the manifest string as either an absolute or relative URL. If manifestUrl is failure, return failure. If manifestUrl same origin configUrl , return failure. If manifestUrl potentially trustworthy URL , return failure. extract the JSON fetch response response response If response network error status ok status , return null. Let mimeType extracting a MIME TYPE response ’s header list . If mimeType JSON MIME Type , return null. Let json parse JSON bytes to an Infra value responseIf the size of discovery’s body . If json json ordered map , return null. Return json . request permission to sign-up IdentityProviderAccount account AccountState accountState["IdentityProviderAPIConfigprovider_urlsmanifestIdentityProviderConfigprovider Let metadata fetch the client metadata manifest provider .relax the size of the provider_urls array. -
If
metadatadiscovery ["privacy_policy_urlprovider_urls"] is defined and the"] is NOT equal to provider ’sclientIdconfigURLaccount ["
-
-
Let configRequest be a new request as follows:
-
approved_clientsurl -
"], then display the metadataconfigUrl["privacy_policy_url -
"] link. If metadata metadata ["redirect mode -
"error"
-
terms_of_service_urlclient -
null
-
"] is defined, and the provider ’swindow -
"no-window"
-
clientIdservice-workers mode -
"none"
-
account ["destination -
"webidentity"
-
approved_clientsorigin -
a unique opaque origin
- header list
-
a list containing a single header with name set to
Accept
and value set toapplication/json
"], then display the metadata ["terms_of_service_url -
"] link. Prompt the user to gather explicit intent to create an account. The user agent MAY use thereferrer policy -
"no-referrer"
-
IdentityProviderBrandingcredentials mode -
"omit"
-
-
to inform the style choices of its UI. If the user does not grants permission, return.Fetch request with configRequest , globalObject , and processResponseConsumeBody set to the following steps given a response response :-
Let json be the result of extract the JSON fetch response from response .
-
Change accountState ’sregistration stateConvert json to anIdentityProviderAPIConfig
stored in config , unless config has been set to failure.unregistered registered .
-
-
Wait for both fetch responses to be completed.
-
Change accountState ’s allows logoutReturn config .
from false to true.
fetch the client metadata
NOTE:
We use a two-tier file system in order to prevent the
IDP
to easily determine the
RP
that a user is visiting by encoding the information in the config file path. We solve this issue by requiring a well-known file to be on the root of the
IDP
. The config file itself can be anywhere, but it will not be used if the user agent does not find it in the well-known file. This allows the
IDP
to keep their actual config files on an arbitary path while allowing the user agent to prevent config file path manipulation to fingerprint (for instance, by including the RP in the path). See
§ 10.3.1 Manifest Fingerprinting
.
IdentityProviderAPIConfig
IdentityProviderConfig
provider
, and
globalObject
, run the following steps. This returns an
IdentityProviderAccountList
. -
Let
clientMetadataUrlaccountsUrl be the result of computing the manifest URL given providermanifest, config ["client_metadata_endpointaccounts_endpoint"]."], and globalObject . -
If
clientMetadataUrl is failure, return null.accountsUrl is failure, return an empty list. -
Let request be a new request
with the following properties:as follows:-
url
clientMetadataUrl -
accountsUrl
-
redirect mode
set to "error" -
"error"
-
client
set to null -
null
-
window
set to "no-window" -
"no-window"
-
service-workers mode
set to "none" -
"none"
-
destination
set to "webidentity" -
"webidentity"
- origin
- header list
-
a list containing a single header with name set to
Accept
and value set toapplication/json
-
referrer RP 's URL (TODO).referrer policy -
"no-referrer"
-
credentials mode
set to "omit" Let clientMetadata IdentityProviderClientMetadata -
"include"
.Note: integrate with Fetch.The credentialed fetch in this algorithm can lead to a timing attack that leaks the user’s identities before the user grants permission. This is an active area of investigation that is being explored here . -
url
-
Let accountsList be null.
-
FetchFetch request with request , globalObject , and processResponseConsumeBody set to the following steps given a response response :-
Let json be the result of extract the JSON fetch response from response .
-
Convert json to an
IdentityProviderClientMetadataIdentityProviderAccountListmetadata . Copy metadata clientMetadata
Note: integrate with Fetch.We should validate the accounts list returned here for repeated ids, as described here . -
-
Return clientMetadata . select an account accountsList AssertWait for accountsList’s size is greater than 1.to be set. -
Display an account chooser displaying the options fromReturn accountsList .Let account id of the account that the user manually selects from the accounts chooser, or null if no account is selected. Return account sign-in AccountState accountState Assert that accountState ’s registration state registered Change accountState ’s allows logout from false to true. create tokens
USVString
accountId
, an
IdentityProviderConfig
provider
, an
IdentityProviderAPIConfig
IdentityCredential
. -
Assert accountState ’s
registration state
is registered . -
Assert accountState ’s
allows logout
is true. -
Let idTokenUrl be the result of computing the manifest URL given provider
manifest, config ["id_assertion_endpoint
"]."], and globalObject . -
If idTokenUrl
is failure, return null.is failure, return failure. -
Let requestBody be a string resulting in concatenating "client_id=", provider ’s
clientId
, "&nonce=", provider ’snonce
, "&account_id=", and accountId . -
Let request be a new request
with the following properties:as follows:- url
-
idTokenUrl
-
mode
set to "POST" -
"POST"
- body
-
redirect mode
set to "error" -
"error"
-
client
set to null -
null
-
window
set to "no-window" -
"no-window"
-
service-workers mode
set to "none" -
"none"
-
destination
set to "webidentity" -
"webidentity"
- origin
- header list
-
a list containing a single header with name set to
Accept
and value set toapplication/x-www-form-urlencoded
- referrer
-
RP 's URL (TODO).
-
credentials mode
set to "include" -
"include"
-
Let
token IdentityProviderToken . Note: integrate with Fetch.credential be null. -
FetchFetch request with request , globalObject , and processResponseConsumeBody set to the following steps given a response response :-
Let json be the result of extract the JSON fetch response from response .
-
Convert json to an
IdentityProviderToken
,fetchedTokentoken . -
Let credential be a new
IdentityCredential
given globalObject ’s realm . -
Set credential ’s
fetchedToken .Note: integrate with Fetch.to token .
-
-
Wait for credential to be set.
-
Return
tokencredential .fetch the manifest
IdentityProviderConfig
provider
, an
IdentityProviderAPIConfig
IdentityProviderAccount
In parallel, perform the following two steps:
account
, and a
globalObject
, run the following steps. This returns an
AccountState
. -
Let
manifestInWellKnown check the well-known fileconfigUrl be the result of running parse url with provider ’s -
Let
manifest fetch the internal manifest provideridpOrigin be the origin corresponding to configUrl .If manifestInWellKnown manifest , otherwise return null. NOTE: IDP RP IDP IDP § 10.3.1 Manifest Fingerprinting . check the well-known file IdentityProviderConfig -
Let rpOrigin be globalObject ’s associated Document
provider provider's origin . -
Let accountId be account ’s
configURLid§ 5.1 The Well-Known File -
Let triple be ( rpOrigin , idpOrigin , accountId ).
-
If state machine map [ triple ] does not exist, set state machine map [ triple ] to a new AccountState .
-
Let accountState be state machine map [ triple ].
-
Return accountState .
provider_urls
IdentityProviderConfig
provider
, a
string
manifestString
, and
globalObject
, perform the following steps. This returns a
URL
or failure. -
Let configUrl
url parserbe the result of running parse url with provider ’sconfigURL
and globalObject .. -
Let manifestUrl be the result of running parse url given manifestString and globalObject .
-
If manifestUrl is failure, let manifestUrl be the result of running parse url given manifestString (the relative URL), globalObject , and configUrl
is failure, return false.(the base URL). Wait until manifestUrl is set again.Note: This means the we allow passing the manifest string as either an absolute or relative URL.
-
Let rootUrl URL .If manifestUrl is failure, return failure. -
Set rootUrl ’s schemeIf manifestUrl is not same origin with configUrl’s scheme, return failure. -
If manifestUrl is not a potentially trustworthy URL , return failure.
-
Return manifestUrl .
-
Assert: These steps are running on the networking task source .
-
Set rootUrl ’s host configUrl ’s hostIf response is a network error or its status is not an ok status , throw a new "NetworkError
"'s registrable domain . -
Set rootUrlLet mimeType be the result of extracting a MIME TYPE from response’s path list «".well-known", "web-identity"».’s header list . -
If
rootUrl potentially trustworthy URL , return false.mimeType is failure or is not a JSON MIME Type , throw a new "NetworkError
" -
Let
request request with the following properties: url rootUrljson be the result of parse JSON bytes to an Infra value passing response ’s body . -
If json is a parsing exception, or if json is not an ordered map , throw a new "
client set to nullNetworkErrorwindow set to "no-window"service-workers mode set to "none"DOMExceptiondestination set to "webidentity". -
Return json .
origin
opaque origin
IdentityProviderAccount
account
, an
AccountState
accountState
, an
header list
list
header
name
Accept
value
application/json
IdentityProviderAPIConfig
config
, an
referrer policy
set to "no-referrer"
IdentityProviderConfig
credentials mode
set to "omit"
Let
check
be false.
provider
, and a
globalObject
, run the following steps. This returns a boolean. -
Assert: These steps are running in parallel .
-
Fetch request processResponseConsumeBody response response :Letjson extract the JSON fetch response responsemetadata be the result of running fetch the client metadata with config , provider , and globalObject . -
If metadata is not null, metadata ["
Convert jsonprivacy_policy_urlIdentityProviderWellKnowndiscovery . If the size discoveryis not in the list of account ["provider_urlsapproved_clients""] is greater than 1, return."], then display the metadata ["privacy_policy_url
"] link.relax the size of the provider_urls array. -
Set check discoveryIf metadata is not null, metadata ["provider_urlsterms_of_service_url""] is"] is defined, and the provider ’sconfigURLclientId. Return check . fetch the internal manifestIdentityProviderConfigapproved_clientsproviderIdentityProviderAPIConfigterms_of_service_urlLet configUrl url parser provider -
Prompt the user to gather explicit intent to create an account. The user agent MAY use the
-
If the user does not grant permission, return false.
-
Change accountState ’s
configURLregistration state. -
If configUrl is failure, return null.Change accountState ’s -
Run aReturn true.
Content Security Policy Level 3
IdentityProviderAPIConfig
connect-src
configUrl
config
and an
IdentityProviderConfig
provider
, run the following steps. This returns an
IdentityProviderClientMetadata
or null. -
Let clientMetadataUrl be the result of computing the manifest URL given provider , config ["
client_metadata_endpoint
"], and globalObject . -
If
configUrl potentially trustworthy URL , return null.clientMetadataUrl is failure, return null. -
Let request be a new request
with the following properties:as follows:-
url
configUrl -
clientMetadataUrl
-
redirect mode
set to "error" -
"error"
-
client
set to null -
null
-
window
set to "no-window" -
"no-window"
-
service-workers mode
set to "none" -
"none"
-
destination
set to "webidentity" -
"webidentity"
- origin
- header list
-
a list containing a single header with name set to
Accept
and value set toapplication/json
-
referrer policy set to "no-referrer"referrer -
RP 's URL (TODO).
-
credentials mode
set to "omit" Let request request url configUrl redirect mode set to "error". -
"omit"
-
url
-
Let
manifest IdentityProviderAPIConfig . Note: integrate with Fetch.metadata be null. -
FetchFetch request with request , globalObject , and processResponseConsumeBody set to the following steps given a response response :-
Let json be the result of extract the JSON fetch response from response .
-
Convert json to an
IdentityProviderAPIConfigIdentityProviderClientMetadatafetchedConfig
-
-
Wait until metadata is set.
-
Copy fetchedConfig manifestReturn metadata .
Note:
integrate
with Fetch.
IdentityProviderAccount
or failure. -
Assert accountsList ’s size is greater than 1.
-
Display an account chooser displaying the options from accountsList .
-
Let account be the
IdentityProviderAccount
of the account that the user manually selects from the accounts chooser, or failure if no account is selected. -
Return
manifestaccount .
-
Assert that accountState ’s
-
Change accountState ’s
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 Party s 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 Party s 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 Sign-in upon return.
await IdentityCredential. logoutRPs([{ url: "https://rp1.example" , accountId: "123" }, { url: "https://rpN.example" , accountId: "456" }]);
IDP
s
can
call
logoutRPs()
to
log
the
user
out
of
the
RP
s
they
are
signed
into.
dictionary {
IdentityCredentialLogoutRPsRequest ; ;required USVString ;
url required USVString ; }; [
accountId Exposed =Window ,SecureContext ]{partial interface IdentityCredential {static Promise <undefined >(
logoutRPs sequence <IdentityCredentialLogoutRPsRequest >); };
logoutRequests
logoutRPs()
method
is
invoked
given
a
list
of
IdentityCredentialLogoutRPsRequest
s
logoutRequests
,
the
user
agent
MUST
execute
the
following
Promise
.
-
Let promise be a new
Promise
. -
Let globalObject be this ’s relevant global object .
In parallel , perform the following steps:
For each request in logoutRequests :
-
Let account be request ’s
accountId
. -
Let triple be ( rpOrigin , idpOrigin , account ).
-
If state machine map [ triple ] does not exist, continue.
-
Let accountState be state machine map [ triple ].
-
If the accountState ’s
registration state
is unregistered or accountState ’sallows logout
is false, continue. -
Let fetchRequest be a new request
with the following properties:as follows:-
url
set to -
request ’s
url
-
mode
set to -
"GET"
-
redirect
mode
set to -
"error"
-
client
set to -
null
-
window
set to -
"no-window"
-
service-workers
mode
set to -
"none"
-
destination
set to -
"webidentity"
-
origin
set to -
a unique opaque origin
-
credentials
mode
set to -
"include"
-
url
-
FetchQueue a global task on the network task source given globalObject to fetch fetchRequest . -
Set the accountState
allows logout
to false.
-
Resolve promise with
[undefined] and return[undefined].
Return promise .
7.5. Backwards Compatibility
Note: go over how we are planning to deal with backwards compatibility.
8. Permissions Policy Integration
FedCM
defines
a
policy-controlled
feature
identified
by
the
string
"
identity-credentials-get
"
.
Its
default
allowlist
is
"self"
.
A
Document
’s
permissions
policy
determines
whether
any
content
in
that
document
is
allowed
to
obtain
a
credential
object
using
the
Browser
API
.
Attempting
to
invoke
navigator.credentials.get({identity:...,
...})
in
documents
that
are
not
allowed
to
use
the
identity-credentials-get
feature
will
result
in
a
promise
rejected
with
a
"
NotAllowedError
"
DOMException
.
This restriction can be controlled using the mechanisms described in Permissions Policy .
Note:
Algorithms
specified
in
Credential
Management
Level
1
perform
the
actual
permissions
policy
evaluation.
This
is
because
such
policy
evaluation
needs
to
occur
when
there
is
access
to
the
current
settings
object
.
The
internal
method
s
modified
by
this
specification
do
not
have
such
access
since
they
are
invoked
in
parallel
by
CredentialsContainer
's
Request
a
Credential
abstract
operation.
9. Security
This section provides a few of the security considerations for the FedCM API. Note that there is a separate section for § 10 Privacy considerations.
9.1. Content Security Policy
The
first
fetches
triggered
by
the
FedCM
API
are
the
manifest
list,
which
is
public,
and
the
internal
manifest.
config
file.
Imagine
a
malicious
script
included
by
(and
running
as)
the
RP
attempting
to
execute
the
FedCM
API
calls
to
a
malicious
IDP
,
one
which
is
not
trusted
by
the
RP
.
If
the
call
is
successful,
this
would
introduce
browser
UI
on
the
RP
with
sign
in
options
into
a
malicious
IDP
.
This
malicious
IDP
could
then
attempt
to
trick
the
user.
The
protection
against
this
attack
is
the
Content
Security
Policy
Level
3
check,
which
would
fail
because
the
origin
of
the
manifest
of
the
malicious
IDP
would
not
be
an
origin
included
in
the
allowlist
specified
by
the
Content
Security
Policy
Level
3
of
the
RP
,
hence
preventing
the
undesired
FedCM
UI
from
being
shown.
Since
any
subsequent
fetches
are
same
origin
with
respect
to
the
internal
manifest
config
file
or
at
least
dependent
on
the
contents
of
the
internal
manifest,
config
file,
they
do
not
require
additional
checks.
The non-same-origin fetches include, for example, the brand icon. The user agent does not perform a Content Security Policy Level 3 check on these because they are directly specified from the manifest. In addition, the rendering of this image is performed by the user agent, and as such this image cannot affect the RP site nor can they be inspected by the RP in any way.
9.2. Sec-Fetch-Dest Header
This section is non-normative.
The
FedCM
API
introduces
several
non-static
endpoints
on
the
IDP
,
so
these
need
to
be
protected
from
XSS
attacks.
In
order
to
do
so,
the
FedCM
API
introduces
a
new
value
for
the
Sec-Fetch-Dest
header,
a
forbidden
header
name
.
The
requests
initiated
by
the
FedCM
API
have
a
webidentity
value
for
this
header.
The
value
cannot
be
set
by
random
websites,
so
the
IDP
can
be
confident
that
the
request
was
originated
by
the
FedCM
browser
rather
than
sent
by
a
websites
trying
to
run
an
XSS
attack.
An
IDP
must
to
check
for
this
header’s
value
in
the
credentialed
requests
it
receives,
which
ensures
that
the
request
was
initiated
by
the
user
agent,
based
on
the
FedCM
API.
A
malicious
actor
cannot
spam
FedCM
API
calls,
so
this
is
sufficient
protection
for
the
new
IDP
endpoints.
9.3. Browser Surface Impersonation
The FedCM API introduces new (trusted) user agent UI, and the user agent may choose to show the UI entirely on top of the page’s contents, if anything because the page was the one responsible for this UI. This introduces a potential concern of a malicious site to try to replicate the FedCM UI, gain the user’s trust that the user is interacting with a trusted browser surface, and gather information from the user that they would only give to the browser rather than the site (e.g. usernames/passwords of another site). This would be hard to achieve because the FedCM UI uses metadata about the user accounts of the IDP , which the malicious website doesn’t have access to. If this is a malicious site, it would not know the user accounts unless the user is already compromised. However, the site could have some guess of the user identity, so the browser is encouraged to provide UI that is hard to replicate and that clearly presents the domains of the parties involved in the website’s FedCM call. Overall, an attacker trying to impersonate the browser using exclusively UI that is accessible to the content area (e.g. iframes) to attempt to retrieve sensitive information from the user would be noticeably different from the FedCM UI. Finally, because the FedCM UI can only be queried from the top-level frame (or potentially from an iframe with explicit permission from the top-level frame), the priviledged UI surface is only shown when the top-level frame wants it so. A sneaky iframe cannot force the FedCM UI to occlude important content from the main page.
10. Privacy
This section is intended to provide a comprehensive overview of the privacy risks associated with federated identity on the web for the purpose of measuring the privacy risks and benefits of proposed browser intermediation designs.
10.1. Principals
This section describes the four principals that would participate in an invocation of the API and expectations around their behavior.
-
The user agent implements § 7 The Browser API and controls the execution contexts for the RP and IDP content. The user agent is assumed to be trusted by the user, and transitively trusted by the RP and IDP .
-
Relying Party s ( RP s) are websites that invoke the FedCM API for the purpose of authenticating a user to their account or for requesting information about that user. Since any site can invoke the API, RP s cannot necessarily be trusted to limit the user information it collects or use that information in an acceptable way.
-
Identity Provider s ( IDP s) are third-party websites that are the target of a FedCM call to attempt to fetch a token . Usually,the IDP has a higher level of trust than the RP since it already has the user’s personal information, but it is possible that the IDP might use the user’s information in non-approved ways. In addition, it is possible that the IDP specified in the API call may not be an IDP the user knows about. In this case, it likely does not have personal user information in advance.
-
A tracker is a third-party website that is not an IDP but could abuse the FedCM API exclusively for the purpose of tracking a user as they visit various websites. A tracker may be injected by the RP with or without their knowledge (e.g. injected into one of the various script tags that the RP embeds that is loaded dynamically), but they usually do not modify the UI of the website, so that it is harder to detect the tracking. A tracker that successfully adds tracking scripts for users in various websites may then use this information for various purposes, such as selling the information about the user. It should not be possible for trackers to use the FedCM API to track users across the web.
Based on the above, the privacy discussion makes the following assumptions:
-
It is not acceptable for an RP , IDP , or tracker to learn that a specific user visited a specific site, without any permission granted by the user. That is, the user agent needs to hide the knowledge that a specific user identity visited a specific site from the RP , IDP , and trackers . It may share this knowledge with the RP and IDP once the user grants permission. In particular, the RP should not know the user identity and the IDP should not know the site that the user has visited before the FedCM flow gathers the user’s permission to do so.
-
It is the user agent 's responsibility to determine when the user has granted permission for the IDP to communicate with the RP in order to provide identification for the user.
-
Once the user agent has determined that the user has granted permission to provide their account information to the RP , it is ok for the IDP and for the RP to learn information about that specific user’s account, as required to provide identification. The RP should not learn about about any other user accounts.
10.2. Network requests
The FedCM API introduces the ability for a site to ask the browser to execute a few different network requests, as shown in the § 4 High Level Design section. It is important for the browser to execute these in such a way that it does not allow the user to be tracked (by an attacker impersonating an IDP ) on to the site using FedCM. The following table has information about the network requests performed:
For fetches that are sent with cookies, we actually consider them equivalent to first-party fetches, and hence include first-party cookies as if the resource was loaded as a first-party, e.g. regardless of the SameSite value (which is used when a resource loaded as a third-party, not first-party). This makes it easy for an IDP to adopt the FedCM API without introducing security issues on the API, since the RP cannot inspect the results from the fetches in any way.
We want to ensure that the FedCM fetches are all same-origin with respect to the provider specified by the RP . The reason for this is because fetches with cookies would use the cookies from the origin specified, so allowing arbitrary origins would introduce confusion and potential privacy issues with regards to which cookies are shared and with whom within the FedCM flow. The easiest way to ensure that all of these fetches remain same-origin is by disabling redirects and checking the origin of the fetched URLs.
-
The manifest fetch can’t be used to track users because it is performed without cookies, client id , or referrer. Thus, anyone could perform this fetch, and the information contained therein is considered public.
-
The accounts fetch can’t be used to track users because it is performed with cookies from the IDP but, importantly, without the client id or referrer. This in theory is a new power that the RP gains that it would not have otherwise. Preventing too many of these fetches may be important, but IDP s are already expected to protect against DoS attacks. In addition, the user agent should only allow one FedCM flow per page at any given moment, immediately rejecting any attempts to start another one. Since a FedCM flow can only be terminated when the user interacts or after a long timer, the number of fetches performed is not a concern. The IDP does learn a lot about the user from this fetch, but this is discussed in detail below.
-
The client metadata fetch can’t be used to track users too because it is performed without cookies from the IDP , albeit with a client id and a referrer. This allows the IDP to communicate the relevant Privacy Policy and Terms of Service to the user agent, in case they need to be displayed. Again, besides possible timing attacks described here, the RP gains nothing from this fetch, and the RP could already perform this fetch if it wanted to since it involves no cookies from the IDP .
-
By design, the token fetch exposes the user at the website to the IDP : it is peformed with cookies, client id , and referrer. Because of that, it is gated on the user interacting with the user agent UI, and enables the IDP to communicate to the RP the information required to perform a federated signin/signup. It is not possible for the RP or the IDP to force the token fetch to happen without user permission, as the user agent cannot be spoofed or otherwise tricked.
10.3. Attack Scenarios
This section describes the scenarios in which various agents might attempt to gain user information. It considers the possibilities when:
For the purposes of this section, a principal is considered to be participating in the collection of information if it directly or indirectly performs actions with the aim of realizing one of the above threats.
Note: An example of indirect collusion would be an RP importing a script supplied by an IDP where the IDP intends to track users.
For the purpose of discussion, this document assumes that third-party cookies are disabled by default and are no longer effective for use in tracking mechanisms, and also some form of mitigations are implemented against ‘bounce tracking’ using link decoration or postMessage. Most of these scenarios consider how user tracking might happen without them. See also Pervasive Monitoring Is an Attack .
10.3.1. Manifest Fingerprinting
Suppose
that
the
FedCM
API
did
not
have
a
two-tier
manifest
(see
the
fetch
the
manifest
create
an
IdentityCredential
algorithm),
and
instead
directly
had
a
single
manifest.
This
would
introduce
the
following
fingerprinting
attack:
// The following will fetch the manifest JSON file, which will know the origin of the RP :( const cred= await navigator. credentials. get({ identity: { providers: [{ configURL: `https://idp.example/ ${ window. location. href} ` }] } });
NOTE: You can read more about the attack described here .
Here, the RP includes identifies itself when fetching the manifest from the IDP . This coupled with the credentialed fetches that the FedCM API performs would enable the IDP to easily track the website that the user is visiting, without requiring any permission from the user. Our mitigation to this problem is to use the § 5.1 The Well-Known File file. We enforce a specifically named file at the root of the IDP 's domain to ensure that the file name does not introduce fingerprints about the RP being visited.
The whole manifest could be in this location, but we instead choose to only point to the real manifest from there. This allows us to have flexibility in the future to allow a small constant number of manifests, should an IDP require this in the future, instead of just a single one. It also helps the IDP 's implementation because they any changes to the manifest are more likely to be performed on a file located anywhere, as opposed to the root of the domain, which may have more constraints in terms of ease of update.
10.3.2. Timing Attacks
In the timing attack, the RP and IDP collude to allow the IDP to compute the ( RP 's origin, IDP 's user identity) pair without the user’s permission. This attack is not deterministic: there is room for statistical error because it requires stitching together two separate pieces of information to track the user. However, it is important to mitigate this attack and ensure that it’s economically impractical to perform. In this attack, we assume that network requests do not have large fingerprinting vectors (e.g. IP addresses). These vary by user agent and are hard to eliminate entirely, but in general user agents are expected to address these over time. These bits of information tied to the network requests make the timing attack easier, making it more important to address.
Note: this attack is described and discussed here .
The attack is as follows:
-
The RP logs the time at which it invokes the API, time A and sends it to the IDP to learn itself by marking the time in which it receives the fetch for the RP 's client metadata. Time A is tied to the site.
-
A credentialed request is sent to the IDP that does not explicitly identify the RP , but it is sent around a time that is close enough to the request above. The IDP notes the time in which this request has arrived, time B. Time B is tied to the user identity.
-
The IDP correlates time A and time B to find the (site, user identity) pair with high probability. Note that fingerprinting can make the correlation more accurate.
Note that this kind of correlation is already possible without FedCM by using simple cross-origin top-level navigations, but using FedCM for this purpose would worsen the problem if it improved timing resolution or if it was less visible to users (e.g. the IDP could return empty accounts to the user agent to deliberately make no browser UI to be triggered, and hence make this attack invisible to the user).
The user agent should mitigate this attack to protect users, in an interoperable way.
The following are mitigations under investigation.
10.3.2.1. Heuristics
One mitigation under investigation is to try to use heuristics to limit the attack surface:
-
Any RP s or IDP s observed to be using this API to compromise user privacy in a deceptive or abusive manner could be explicitly blocked from using it or put behind an interstitial.
-
The user agent could detect trackers by noting alleged IDP s that do either of the following:
-
Never show UI despite the FedCM API fetches being performed.
-
Provide generic user identification, such as "Anonymous", or "Guest" or "Incognito" as the user’s name.
-
Have a suspiciously low click-through rate (e.g. most users don’t recognize the value in using this IDP ).
-
-
The user agent could block the API or show a static interstitial after the user has already expressed lack of interest in the API because they did at least one of the following:
-
Repeatedly ignored the FedCM API in the past in a similar scenario.
-
Provide user settings to disable the FedCM API.
-
Pressed some user agent UI to close the FedCM API’s request for permission.
-
-
The user agent could gate the FedCM fetches on a user interaction so that the timing attack is only possible once the user has expressed some interest in the API. Note that this may provide a poor user experience for users that do want to use the API, and may also result in worse success metrics for the API.
10.3.2.2. Push Model
Another potential future mitigation for timing attacks is the push model . The current API is the pull model : the API pulls the user accounts from the IDP every time they are needed by the FedCM API. In the push model , the IDP needs to tell the user agent that a user has signed in whenever this happens. This way, when the FedCM API is called, the user agent already knows the user accounts that the user can select from, and thus does not require any credentialed fetches to the IDP in order to show the UI. It would only be when the user grants permission that the IDP is notified, thus resolving the timing attack problem entirely.
While the push model seems like an improvement for privacy, the current API uses the pull model for these reasons:
-
It introduces a lot of complexity for the IDP s, as they now need to declare the user accounts and keep them updated all the time. In particular, they need to be updated when a user logs out, deletes their account or simply change name, etc. A user can also use browser UX to logout, e.g. by clearing cookies. While those are not high-frequency changes (e.g. once every other year for each user), keeping them in sync is non-trivial.
-
It requires a lot of the IDP 's trust in user agent to protect all of their user’s accounts. The push model requires storing all of the user accounts from all of the IDP s that a user is logged into, regardless of whether the user ever uses the FedCM API or not. This means that all users pay the cost, and only some get the reward.
10.3.2.2.1. The IdP Sign-in Status API
this is a more formal description of what is proposed here .
A strict subset of the push model that seems promising is to only push the user’s sign-in status in the IdP (as opposed to the entirety of the user’s account data, e.g. name, email).
Since the sign-in status is specific to a browser instance/profile, this bit can reflect reality almost perfectly (with the exception of server-side invalidations, e.g. users changing password, and deleting accounts on other devices).
Importantly, sign-in status seems easier to degrade gracefully when the client-side state is inconsistent with the server-side state: re-authentication UX. The user’s profile information, on the other hand, has a series of legal freshness requirements that are still not quite well understood.
So, in this variation, the user agent does two things: (a) it stores the user’s login status at each IDP and (b) exposes APIs that allows IDP s to change them.
This is a compelling variation because (a) it is comparably simpler to implement by IDPs and (b) if the user agent knew whether the user is signed-in or not to the IDP , it can guarantee that a user prompt will always be displayed, which makes the timing attack much less viable to be performed invisibly (i.e. without any explicit and observable indication to the user).
Internally, each user agent keeps track of a global Sign-in Status map per IDP , initially an empty map . The keys in the Sign-in Status map is the origin of the IDP . The values in the Sign-in Status map are status objects which can be one of the following values:
-
unknown
(default) -
By default, the user agent assumes that the user’s signed in status is undefined.
-
signed-in
-
The user has explicitly signed-in to the IDP.
-
signed-out
-
The user has explicitly signed-out to the IDP.
The IDPs are provided with an API that allows them to set their Sign-in Status .
[Exposed =Window ,SecureContext ]interface {
IdentityProvider static undefined ();
login static undefined (); };
logout
login()
static
method
is
invoked
the
user
agent
MUST
execute
the
following
steps:
-
Let origin be the current settings object 's origin .
-
Set the Sign-in Status of the origin to
signed-in
.
logout()
static
method
is
invoked
the
user
agent
MUST
execute
the
following
steps:
-
Let origin be the current settings object 's origin .
-
Set the Sign-in Status of the origin to
signed-out
.
For example:
IdentityProvider. login(); // ... later ... IdentityProvider. logout();
For convenience and compatibility with existing deployed flows, the user agent also exposes the ability for IDPs to control their Sign-in Status via HTTP headers:
IdP-Sign-in-Status: action=login // ... later ... IdP-Sign-in-Status: action=logout
When
site
data
(e.g.
cookies)
are
cleared
manually
by
the
user,
the
user
agent
also
sets
the
Sign-in
Status
to
unknown
.
IDPs
are
also
offered
an
extension
to
the
IdentityProviderAPIConfig
object
to
include:
-
signin_url
(optional) -
A URL that allows a user to sign-in to the IDP .
The
user
agent
uses
the
following
maybe
fetch
the
accounts
list
in
the
potentially
create
IdentityCredential
algorithm,
as
opposed
to
instead
of
the
fetch
the
accounts
list
algorithm.
It
would
also
return
early
on
the
potentially
create
IdentityCredential
algorithm
if
the
user
was
signed-out
.
IdentityProviderAPIConfig
IdentityProviderConfig
provider
-
Let configUrl be the result of running parse url
parserwith provider ’sconfigURL
and globalObject .. -
Let idpOrigin be the origin corresponding to configUrl .
-
Let status be the Sign-in Status of the idpOrigin .
-
If status is
unknown
:-
Let accounts be the result of the fetch the accounts list algorithm given
manifestconfig and provider . -
Set the Sign-in Status of the idpOrigin to
signed-in
if accounts is non-empty,signed-out
otherwise.
NOTE: This handles the case where the IDP hasn’t had the chance to call the API before the accounts list is needed. This can incur into a timing attack, but it is limited to 1 per IDP per user agent , so not very practical. Albeit small, removing this attack surface is an active area of investigation.
-
-
If status is
signed-out
:-
Return an empty list.
NOTE: By terminating the request here before running fetch the accounts list algorithm we prevent the timing attack to be performed without any user prompt.
-
-
If status is
signed-in
:-
Let accounts be the result of the fetch the accounts list algorithm given
manifestconfig and provider . -
If accounts ’s size is 0:
-
Set the Sign-in Status of the idpOrigin to
signed-out
. -
Ask the user to confirm they want to sign-in to their IDP .
-
If they decline, return an empty list.
-
Return the result of running the Sign-in to the IDP algorithm given
manifestconfig and provider .
NOTE: This can happen when the user’s local client credentials are invalidated on the server (e.g. changing passwords or deleting accounts on a different device), or we get network errors (e.g. timeouts, failures, etc).
-
-
Return accounts .
-
IdentityProviderAPIConfig
IdentityProviderConfig
provider
-
Let configUrl be the result of running parse url
parserwith provider ’sconfigURL
. -
Let idpOrigin be the origin corresponding to configUrl .
-
Assert that the Sign-in Status of the idpOrigin is
signed-out
. -
In parallel, wait until one of the following tasks returns to continue:
-
Open a dialog that directs the user to the
manifestconfig ’ssignin_url
. -
Wait until the Sign-in Status of the idpOrigin becomes
signed-in
-
Close the dialog
-
Return the result of the fetch the accounts list algorithm
-
-
Wait until the user explicitly cancels the dialog
-
Close the dialog
-
Return empty list
-
-
10.3.3. IDP Intrusion
From Target Privacy Threat Model § hl-intrusion
Privacy harms don’t always come from a site learning things.
From RFC6973: Intrusion
Intrusion consists of invasive acts that disturb or interrupt one’s life or activities. Intrusion can thwart individuals' desires to be left alone, sap their time or attention, or interrupt their activities.
In the context of federation, intrusion happens when an RP and an IDP are colluding to invasively and aggressively recommend the user to login disproportionally to the their intent. Much like unsolicited notifications, an RP can collude with an IDP to aggressively log users in.
The user agent can mitigate this by mediating the user controls and offering them proportionally to the intent of the user or the privacy risks involved. For example, a user agent can choose to show a loud / disruptive modal mediated dialog when it has enough confidence of the user’s intent or show a quiet / conservative UI hint when it doesn’t.
A user agent could also choose to control disruption of the user’s experience based on the risks involved. For example, when a directed identifier is being exchanged it can be more confident of the unintended consequeces and offer a more aggressive user experience, whereas when global identifiers are exchanged a more conservative user experience.
10.4. Other Attack Scenarios
The following are other attack scenarios considered but for which we do not currently have specific mitigations in this API, but would ideally like to see addressed in future revisions of this API. This is usually because the attacks rely on the user already granted permission. Usually stopping such attacks would be very hard since the RP and IDP communication has been established. In addition, such attacks would still be possible when using regular login mechanisms. Still, they are worth mentioning as they showcase some risks users take when signing into RP s. In some cases, future mitigations are discussed.
10.4.1. Cross-Site Correlation
This attack happens when multiple RP s collude to use their user’s data to correlate them and build a richer profile. When a user willingly provides their full name, email address, phone number, etc, to multiple relying parties, those relying parties can collaborate to build a profile of that user and their activity across collaborating sites. Sometimes this is referred to as joining since it amounts to a join of user records between the account databases of multiple RPs. This correlation and profile-building is outside the user’s control and entirely out of the user agent ’s or IDP ’s view.
-
User signs into RP1 (which sells jewelry) with an IDP, providing to RP1 their email address user@email.example
-
User signs into RP2 (which sells houses) with an IDP, providing to RP2 their email address user@email.example
-
User browses the collection of wedding rings in RP1.
-
Out of band, RP1 tells RP2 that user@email.example is shopping for wedding rings
-
User browses the housing inventory in RP2.
-
RP2 uses the fact that the user is shopping for wedding rings in RP1 to advertise and filters their housing inventory.
-
User is surprised that RP2 knows that they are shopping for wedding rings.
The problem of RP s joining user data via back-channels is inherent to the proliferation of identifying user data. This can be solved by issuing directed identifiers that provide an effective handle to a user’s identity with a given IDP that is unique and therefore cannot be correlated with other RP s. In the past, there have been schemes to accomplish this using one-way hashes of, for example, the user’s name, the IDP , and the RP . These identifiers would be unique, and hence it would not be possible to correlate these with other RP s.
10.4.2. Unauthorized Data Usage
Another attack is when the RP or IDP uses user information for purposes not authorized by the user. When the user agrees to allow the IDP to provide information to the RP , the permission is specific to certain purposes, such as sign-in and personalization. For instance, the RP might use that data for other purposes that the user would not expect and did not authorize, such as selling email addresses to a spam list. Spamming risk can exist even when using directed identifiers .
10.4.3. RP Fingerprinting
This attack happens when the RP employs client state-based tracking to identify user. Any API that exposes any kind of client state to the web risk becoming a vector for fingerprinting. The purpose of this API is for the user to provide identification to the RP . And the user should be able to rescind the access to that identification, for instance by logging out. However, a tracking RP could keep state to detect the user that was previously logged in:
10.4.4. Secondary Use
Secondary use is the use of collected information about an individual without the individual’s perimssion for a purpose different from that for which the information was collected. This attack happens when IDP s misuse the the information collected to enable sign-in for other purposes.
Existing federation protocols require that the IDP know which service is requesting a token in order to allow identity federation. Identity providers can use this fact to build profiles of users across sites where the user has decided to use federation with the same account. This profile could be used, for example, to serve targeted advertisements to those users browsing on sites that the IDP controls.
This risk can exist even in the case where the IDP does not having pre-existing user account information (for instance, if it is not a _bona fide_ IDP), because FedCM requests sent to the IDP are credentialed. This is more likely to occur if the RP is colluding with the IDP to enable tracking via § 10.3.2 Timing Attacks .
-
User signs into RP1 (which sells jewelry) with an IDP .
-
User signs into RP2 (which sells houses) with the same IDP .
-
User navigates to the IDP .
-
Because the IDP knows that the user has an account with RP1 and RP2, the IDP can show ads about vacations for honeymoons.
-
The user is surprised that their IDP is aware of their plans to get married.
Preventing tracking of users by the IDP is difficult: the RP has to be coded into the identity token for security reasons, such as token reuse and fraud and abuse prevention. That said, there have been cryptographic schemes developed to blind the IDP to the RP while still preventing token reuse(see Mozilla’s personas ).
11. Extensibility
Note: go over the extensibility mechanisms.
12. Acknowledgements
Note: write down the Acknowledgements section.