A proposal to extend FedCM to support open federations, in which a relying party accepts any identity provider that implements a given protocol.
Spec: https://w3c-fedid.github.io/idp-registration/
Stage
This is a Stage 1 proposal.
Champions
- @samuelgoto
- @aaronpk
- @anderspitman
- @ThisIsMissEm
Participate
The problem
Web applications, or relying parties (RPs), use federated sign-in to authenticate users with an account they already have at an identity provider (IdP). FedCM lets the browser mediate this exchange: the RP lists the IdPs it accepts by their config URLs, and the browser shows the user's accounts at those IdPs.
This model assumes a closed federation: the RP knows in advance every IdP it accepts, and has a relationship with each of them.
In an open federation, any server that implements the federation's protocol can act as an IdP, and RPs accept all of them without a prior relationship. Examples:
- IndieAuth: users are identified by a URL, e.g.
https://alice.example. - AT Protocol: users are identified by a handle, e.g.
@alice.example. - ActivityPub servers: users are identified by an address, e.g.
alice@social.example. - Solid: users are identified by a WebID.
Email works as an open federation in the same sense: an RP accepts an address at any mail domain.
Open-federation protocols typically ask the user to type an identifier (a URL, handle or address), so that the RP can discover the user's IdP from it. This requires users to know their identifier and to understand what the prompt is asking for.
OpenID 2.0 used this approach, which, according to one of its authors, deployments declined by about half after their peak, as it became clear that average users did not know what to do with the OpenID prompt.
This proposal extends FedCM so that:
- an RP can request any IdP in an open federation, identified by a URL, without listing IdPs;
- the user can select an existing account without typing an identifier.
The proposal
The browser keeps a list of the user's handles, such as @alice.example, alice@social.example or https://alice.example. An RP can then request any IdP that is the issuer of one of those handles and supports a federation the RP accepts.
1. The IdP registers the user's handle after the user signs in, with the user's permission:
await navigator.login.setStatus("logged-in", { accounts: [{ id: "1234", name: "Alice", handle: "@alice.example" }] }); await IdentityProvider.register("@alice.example");
The browser asks the user whether to save the handle:
2. The RP requests a federation (a protocol or profile, identified by a URL) instead of specific IdPs:
const credential = await navigator.credentials.get({ identity: { providers: [{ federation: "https://www.w3.org/TR/indieauth/", params: { nonce: "..." } }] } });
The browser shows the accounts for the registered handles whose IdP lists that federation in its config file:
3. The user can type a handle that isn't registered yet. The browser resolves it to its IdP and adds it to the registered handles:
A handle's IdP is determined by the handle's domain, which can delegate to another site with a DNS record. The browser does not need protocol-specific logic. See Handles in the spec for how handles are parsed and resolved.
Privacy. A registered IdP receives no credentialed request before the user selects an account or chooses to sign in. This avoids the timing attack and the mismatch UI associated with FedCM's accounts endpoint. See Privacy considerations.
Alternatives considered
- Registering through
navigator.login.setStatus(). A registered handle has to outlive the user's session, while login status changes every time the user signs in or out. Registration can also show a prompt, which wouldn't work for theSet-Loginheader. See The Handle Registry. - Registering a config URL instead of a handle. With handles, registration by an IdP and entry by the user follow the same path, and a handle can move to another IdP without being registered again.
- Passing the supported federations in
register(). Listing them in the config file means an IdP doesn't need to register again when the list changes.
Where things are
- Chrome and Firefox have expressed support (example), and Chrome has a prototype behind a flag.
- Members of the IndieWeb and Solid communities have built prototype IdPs, RPs and protocol profiles, for example FedCM for IndieAuth.
Open questions
The main open question is whether RPs will adopt it. When the user has no registered IdPs in the requested federation, the call shows nothing, so the cost to an RP of trying it is low. The spec tracks other open questions as inline issues.