1. Introduction
This section is non-normative.
In Federated Credential Management API, when an RP requests an IDP whose login status is
logged-in, the user agent sends a credentialed request to the IDP’s
accounts_endpoint before the user has chosen an account. That
credentialed fetch enables a timing attack and requires the user agent to show mismatch UI when the
endpoint returns no accounts.
This specification lets an IDP push the user’s signed-in accounts to the user agent
when calling setStatus(), as described in
Lightweight FedCM:
https://idp.example, the IDP pushes her account when setting its
login status:
await navigator. login. setStatus( "logged-in" , { accounts: [{ id: "1234" , name: "Alice" , email: "alice@idp.example" , picture: "https://idp.example/alice.jpg" }] });
Because idp.example pushes its accounts, its config file does not need an
accounts_endpoint:
{ "id_assertion_endpoint" : "/assertion" , "login_url" : "/login" }
This specification is written as a set of monkey patches to Login Status API and Federated Credential Management API, shown like this:
2. Infrastructure
This specification depends on the Infra Standard. Infra Standard
3. The Account Registry
Each user agent has a global, persistent account registry, which stores the accounts
that IDPs push with setStatus(). It is an initially empty map. Its
keys are origins of IDPs, and its values are
account registry entries. An account registry entry is
a struct with the following items:
- accounts
-
A list of
IdentityProviderAccounts. - expiration
-
A moment in time, or null for no expiration.
dictionary {LoginStatusOptions sequence <IdentityProviderAccount >accounts ; [EnforceRange ]unsigned long long expiration ; };
accounts, of type sequence<IdentityProviderAccount>-
The list of
IdentityProviderAccounts currently signed in at the IDP. expiration, of type unsigned long long-
The duration in milliseconds for which the pushed accounts remain valid. If omitted, the accounts remain valid until the IDP’s login status becomes logged-out or is cleared.
setStatus() method so that it takes an optional
second argument, optional LoginStatusOptions options = {}, and add the following steps at the
end of its algorithm:
-
If status is
"logged-out", remove account registry[origin] and return. -
For each account of options["
accounts"]: if account is not displayable, throw aTypeError. -
Let expiration be null.
-
If options["
expiration"] exists, set expiration to the current time plus options["expiration"] milliseconds. -
Set account registry[origin] to a new struct with accounts options["
accounts"] and expiration expiration.
Also, in the algorithm that processes the Set-Login header, when the token is
"logged-out", remove account registry[origin].
IdentityProviderAccounts.
-
If account registry[origin] does not exist, return an empty list.
-
Let entry be account registry[origin].
-
If entry’s expiration is not null and is in the past, remove account registry[origin] and return an empty list.
-
If get the login status for origin is not logged-in, return an empty list.
-
Return entry’s accounts.
The user agent MUST clear account registry entries whenever it clears the corresponding Login Status map entries.
4. Presentation
This section defines how the user agent uses the account registry when presenting accounts in Federated Credential Management API.
required keyword from the
accounts_endpoint member of IdentityProviderAPIConfig.
In fetch the config file, if
config.accounts_endpoint doesn’t exist, set
accounts_url to null instead of computing it, and do not treat a null
accounts_url as failure.
Note: An IDP that pushes its accounts with setStatus() only needs a
config file and an id_assertion_endpoint.
-
Let origin be the origin of the result of running the URL parser on provider’s
configURL. -
Let pushed be the result of get the pushed accounts for origin.
-
If pushed is not empty, or if config["
accounts_endpoint"] doesn’t exist, return a newIdentityProviderAccountListwithaccountsset to pushed.
5. Privacy and security considerations
-
An IDP that pushes its accounts and omits
accounts_endpointnever receives a credentialed request before the user selects an account or chooses to sign in. This removes the timing attack that affectsaccounts_endpoint. -
The account registry is global to the user agent, is used only in user agent UI, and is never exposed to the RP until the user selects an account.
-
Entries in the account registry are scoped to the IDP’s origin, expire when
expirationelapses, and are cleared whenever the IDP sets its login status to logged-out or the user clears browsing data for that origin.