Account Registry API

Draft Community Group Report,

This version:
https://w3c-fedid.github.io/idp-registration/account-registry.html
Issue Tracking:
GitHub
Editor:
(Google Inc.)

Abstract

This specification extends the Login Status API Login Status API and the Federated Credential Management API Federated Credential Management API so that an identity provider can push the user’s signed-in accounts to the user agent when setting its login status, allowing the user agent to present those accounts without fetching the identity provider’s accounts endpoint.

Status of this document

This specification was published by the Federated Identity Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

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:

After Alice signs in on 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:

A change to an algorithm or definition in another specification.

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.

In Login Status API, change the setStatus() method so that it takes an optional second argument, optional LoginStatusOptions options = {}, and add the following steps at the end of its algorithm:
  1. If status is "logged-out", remove account registry[origin] and return.

  2. If options["accounts"] does not exist, return.

  3. For each account of options["accounts"]: if account is not displayable, throw a TypeError.

  4. Let expiration be null.

  5. If options["expiration"] exists, set expiration to the current time plus options["expiration"] milliseconds.

  6. 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].

To get the pushed accounts for an origin origin, run the following steps. This returns a list of IdentityProviderAccounts.
  1. If account registry[origin] does not exist, return an empty list.

  2. Let entry be account registry[origin].

  3. If entry’s expiration is not null and is in the past, remove account registry[origin] and return an empty list.

  4. If get the login status for origin is not logged-in, return an empty list.

  5. 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.

In Federated Credential Management API, remove the 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.

In fetch the accounts, insert the following steps at the beginning of the algorithm:
  1. Let origin be the origin of the result of running the URL parser on provider’s configURL.

  2. Let pushed be the result of get the pushed accounts for origin.

  3. If pushed is not empty, or if config["accounts_endpoint"] doesn’t exist, return a new IdentityProviderAccountList with accounts set to pushed.

5. Privacy and security considerations

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. Key words for use in RFCs to Indicate Requirement Levels

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[FEDCM]
Nicolas Pena Moreno. Federated Credential Management API. URL: https://w3c-fedid.github.io/FedCM/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[LOGIN-STATUS]
Login Status API. Editor's Draft. URL: https://w3c-fedid.github.io/login-status/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[URL]
Anne van Kesteren. URL Standard. Living Standard. URL: https://url.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

IDL Index

dictionary LoginStatusOptions {
  sequence<IdentityProviderAccount> accounts;
  [EnforceRange] unsigned long long expiration;
};