-1. Let |origin| be the response's [=response/URL=]'s [=/origin=].
-1. Let |client| be the [=/request=]'s [=request/client=].
-1. If the request's [=request/destination=] is not `"document"`:
- 1. If |client| is null, return.
- 1. If |origin| is not [=same origin=] with the [=/request=]'s
- [=request/origin=], return.
- 1. If |client| is not [=same-origin with its ancestors=], return.
-1. Assert that |value| is a tuple.
-1. Let |token| be the first entry of |value|.
-1. If |token| is `"logged-in"`, [=set the login status=] for |origin|
- to [=logged-in=].
-1. If |token| is `"logged-out"`, [=set the login status=] for |origin|
- to [=logged-out=].
-
-
-
-### JavaScript API ### {#login-status-javascript}
-
-[=IDPs=] can also use a JavaScript API to update the stored login status:
-
-
-
-When {{NavigatorLogin/setStatus()}} is called with argument |status|:
-1. If the [=current settings object=] is not [=same-origin with its ancestors=],
- throw a {{SecurityError}} {{DOMException}}.
-1. Let |origin| be the [=current settings object=]'s
- [=environment settings object/origin=].
-1. Let |value| be [=logged-in=] if |status| is `"logged-in"` or [=logged-out=]
- if |status| is `"logged-out"`.
-1. [=Set the login status=] for |origin| to |value|.
-
-
-
-### Clearing the Login Status Map data ### {#login-status-clear-data}
-
-User agents MUST also clear the [=Login Status map=] data when:
- : the user clears all cookies or site settings data
- :: The user agent MUST clear the entire map.
- : the user clears all cookies or all site data for a specific origin
- :: The user agent MUST remove all entries that would be affected
- by the deleted cookies, that is, any entry with an origin
- to which a deleted cookie could be sent to.
-
- Note: For example, domain cookies may affect subdomains of
- the deleted origin, e.g. clearing cookies for `google.com`
- should also reset the login status for `accounts.google.com`,
- since it may rely on a domain cookie for google.com.
- : the user deletes individual cookies (if allowed by the user agent)
- :: the behavior is user agent-defined.
-
- Note: The user agent MAY want to reset the state to [=unknown=],
- since is impossible to know whether this cookie affects
- authorization state.
- : the user agent receives a
-To
compute the connection status given an {{IdentityProviderConfig}} |provider|, an
-{{IdentityProviderAccount}} |account|, and a |globalObject|, run the following steps. This returns
-
connected or
-
disconnected.
- 1. If |account| [=map/contains=] {{IdentityProviderAccount/approved_clients}} and
- |account|'s {{IdentityProviderAccount/approved_clients}} does not [=list/contain=]
- |provider|'s {{IdentityProviderConfig/clientId}}, return
- [=compute the connection status/disconnected=].
+
+To compute the connected account key given an {{IdentityProviderConfig}} |provider|, an
+{{IdentityProviderAccount}} |account|, and a |globalObject|, run the following steps. It returns a
+triple of the form (rp, idp, account).
1. Let |configUrl| be the result of running [=parse url=] with |provider|'s
{{IdentityProviderConfig/configURL}} and |globalObject|.
1. Let |idpOrigin| be the [=url/origin=] corresponding to |configUrl|.
1. Let |rpOrigin| be |globalObject|'s [=associated Document=]'s [=Document/origin=].
1. Let |accountId| be |account|'s {{IdentityProviderAccount/id}}.
- 1. Let |triple| be (|rpOrigin|, |idpOrigin|, |accountId|).
- 1. If [=connected accounts set=] [=list/contains=] |triple| , return
+ 1. Return (|rpOrigin|, |idpOrigin|, |accountId|).
+
+
+
+When asked whether an {{IdentityProviderAccount}} |account| is
+eligible for auto reauthentication given an {{IdentityProviderConfig}} |provider| and a
+|globalObject|, run the following steps. This returns a boolean.
+ 1. If |account| [=map/contains=] {{IdentityProviderAccount/approved_clients}} and
+ |account|'s {{IdentityProviderAccount/approved_clients}} does not [=list/contain=]
+ |provider|'s {{IdentityProviderConfig/clientId}}, return false.
+ 1. Let |triple| be the result of running [=compute the connected account key=] given |provider|,
+ |account|, and |globalObject|.
+ 1. Return whether [=connected accounts set=] [=list/contains=] |triple|.
+
+
+
+When asked to compute the connection status given an {{IdentityProviderAccount}}
+|account|, an {{IdentityProviderConfig}} |provider| and a |globalObject|, run the following steps.
+This returns connected or
+disconnected.
+ 1. If |account| [=map/contains=] {{IdentityProviderAccount/approved_clients}}:
+ 1. If |account|'s {{IdentityProviderAccount/approved_clients}} [=list/contains=]|provider|'s
+ {{IdentityProviderConfig/clientId}}, return [=compute the connection status/connected=].
+ 1. Return [=compute the connection status/disconnected=].
+ 1. Let |triple| be the result of running [=compute the connected account key=] given |provider|,
+ |account|, and |globalObject|.
+ 1. If [=connected accounts set=] [=list/contains=] |triple|, return
[=compute the connection status/connected=].
- 1. Otherwise, return [=compute the connection status/disconnected=].
+ 1. Return [=compute the connection status/disconnected=].
@@ -535,6 +442,7 @@ This specification introduces a new type of {{Credential}}, called an {{Identity
interface IdentityCredential : Credential {
static Promise<undefined> disconnect(optional IdentityCredentialDisconnectOptions options = {});
readonly attribute USVString? token;
+ readonly attribute boolean isAutoSelected;
};
@@ -544,6 +452,10 @@ This specification introduces a new type of {{Credential}}, called an {{Identity
: {{IdentityCredential/token}}
:: The {{IdentityCredential/token}}'s attribute getter returns the value it is set to.
It represents the minted {{IdentityProviderToken/token}} provided by the [=IDP=].
+ : {{IdentityCredential/isAutoSelected}}
+ :: {{IdentityCredential/isAutoSelected}}'s attribute getter returns the value it is
+ set to. It represents whether the user's identity credential was automatically selected when
+ going through the UI flow which resulted in this {{IdentityCredential}}.
: {{Credential/[[type]]}}
:: The {{IdentityCredential}}'s {{Credential/[[type]]}}'s value is "identity".
: {{Credential/[[discovery]]}}
@@ -590,10 +502,10 @@ When asked to attempt to disconnect given an {{IdentityCredentialDisc
"{{NetworkError}}" {{DOMException}}.
1. If the user has disabled the FedCM API on the |globalObject|, [=reject=] |promise| with a
"{{NetworkError}}" {{DOMException}}.
- 1. If there does not exist an account |account| such that [=compute the connection status=] of
- |options|, |account|, and |globalObject| returns
- [=compute the connection status/connected=], then [=reject=] |promise| with a
- "{{NetworkError}}" {{DOMException}}. This check can be performed by iterating over the
+ 1. If there does not exist an account |account| such that [=connected accounts set=]
+ [=list/contains=] the result of [=compute the connected account key=] given |account|,
+ |options|, and |globalObject|, then [=reject=] |promise| with a "{{NetworkError}}"
+ {{DOMException}}. This check can be performed by iterating over the
[=connected accounts set=] or by keeping a separate data structure to make this lookup fast.
1. Let |config| be the result of running [=fetch the config file=] with
|provider| and |globalObject|.
@@ -758,7 +670,7 @@ dictionary IdentityProviderRequestOptions : IdentityProviderConfig {
agent to show to the user. If provided, the user agent will not show accounts which do not
match this login hint value. It generally matches some attribute from the desired
{{IdentityProviderAccount}}.
- : {{IdentityProviderConfig/domainHint}}
+ : {{IdentityProviderRequestOptions/domainHint}}
:: A string representing the domain hint corresponding to a domain which the [=RP=] is
interested in, or "any" if the [=RP=] wants any account associated with at least one domain
hint. If provided, the user agent will not show accounts which do not match the domain hint
@@ -891,8 +803,8 @@ the exception thrown.
1. Let |config| be the result of running [=fetch the config file=] with
|provider| and |globalObject|.
1. If |config| is failure, return (failure, false).
- 1. Fetch accounts list step: Let |accountsList| be the result of
- [=fetch the accounts list=] with |config|, |provider|, and |globalObject|.
+ 1. Fetch accounts step: Let |accountsList| be the result of
+ [=fetch the accounts=] with |config|, |provider|, and |globalObject|.
1. If |accountsList| is failure, or the size of |accountsList| is 0:
1. [=Set the login status=] for the [=/origin=] of the
{{IdentityProviderConfig/configURL}} to [=logged-out=].
@@ -928,7 +840,7 @@ the exception thrown.
1. If |result| is failure, return (failure, true). The user
agent MAY show a dialog to the user before or after
returning failure indicating this failure.
- 1. Otherwise, go back to the [=fetch accounts list step=].
+ 1. Otherwise, go back to the [=fetch accounts step=].
1. Assert: |accountsList| is not failure and the size of |accountsList| is not 0.
1. [=Set the login status=] for the [=/origin=] of the
@@ -938,14 +850,14 @@ the exception thrown.
{{IdentityProviderAccount/login_hints}} does not [=list/contain=] |provider|'s
{{IdentityProviderRequestOptions/loginHint}}.
1. If |accountList| is now empty, go to the [=mismatch dialog step=].
- 1. If |provider|'s {{IdentityProviderConfig/domainHint}} is not empty:
+ 1. If |provider|'s {{IdentityProviderRequestOptions/domainHint}} is not empty:
1. For every |account| in |accountList|:
- 1. If {{IdentityProviderConfig/domainHint}} is "any":
+ 1. If {{IdentityProviderRequestOptions/domainHint}} is "any":
1. If |account|'s {{IdentityProviderAccount/domain_hints}} is empty, remove
|account| from |accountList|.
1. Otherwise, remove |account| from |accountList| if |account|'s
{{IdentityProviderAccount/domain_hints}} does not [=list/contain=] |provider|'s
- {{IdentityProviderConfig/domainHint}}.
+ {{IdentityProviderRequestOptions/domainHint}}.
1. If |accountList| is now empty, go to the [=mismatch dialog step=].
1. For each |acc| in |accountsList|:
1. If |acc|["{{IdentityProviderAccount/picture}}"] is present, [=fetch the account picture=]
@@ -957,47 +869,42 @@ the exception thrown.
1. Let |registeredAccount|, |numRegisteredAccounts| be null and 0, respectively.
1. Let |account| be null.
1. For each |acc| in |accountsList|:
- 1. Let |accState| be the result of running the [=compute the connection status=] algorithm given
- |provider| and |acc|.
- 1. If |accState| is [=compute the connection status/connected=], set |registeredAccount| to
- |acc| and increase |numRegisteredAccounts| by 1.
- 1. Let |permission| and |disclosureTextShown| both be false.
+ 1. If |acc| is [=eligible for auto reauthentication=] given |provider|, and |globalObject|,
+ set |registeredAccount| to |acc| and increase |numRegisteredAccounts| by 1.
+ 1. Let |permission|, |disclosureTextShown|, and |isAutoSelected| be set to false.
1. If |mediation| is not "{{CredentialMediationRequirement/required}}", |requiresUserMediation|
is false, and |numRegisteredAccounts| is equal to 1:
- 1. Set |account| to |registeredAccount| and |accountState| to the result of running
- [=compute the connection status=] algorithm given |provider| and |account|. When doing this,
- the user agent MAY show some UI to the user indicating that they are being
+ 1. Set |account| to |registeredAccount| and |permission| to true. When doing this, the user
+ agent MAY show some UI to the user indicating that they are being
auto-reauthenticated.
+ 1. Set |isAutoSelected| to true.
1. Otherwise, if |mediation| is "{{CredentialMediationRequirement/silent}}", return (failure, true).
1. Otherwise, if |accountsList|'s size is 1:
1. Set |account| to |accountsList|[0].
- 1. Set |accountState| to the result of running the [=compute the connection status=] algorithm
- given |provider|, |account|, and |globalObject|.
- 1. If |accountState| is [=compute the connection status/disconnected=],
- let |permission| be the result of running [=request permission to sign-up=] algorithm
- with |account|, |accountState|, |config|, |provider|, and |globalObject|. Also set
- |disclosureTextShown| to true.
- 1. Otherwise, show a dialog to request user permission to sign in via |account|, and set the
- result in |permission|. The user agent MAY use |options|'s
+ 1. If [=compute the connection status=] of |account|, |provider| and |globalObject| returns
+ [=compute the connection status/connected=], show a dialog to request user permission to sign
+ in via |account|, and set the result in |permission|. The user agent MAY use |options|'s
{{IdentityCredentialRequestOptions/context}} to customize the dialog.
+ 1. Otherwise, let |permission| be the result of running [=request permission to sign-up=]
+ algorithm with |account|, |config|, |provider|, and |globalObject|. Also set
+ |disclosureTextShown| to true.
1. Otherwise:
1. Set |account| to the result of running the [=select an account=] from the
|accountsList|.
1. If |account| is failure, return (failure, true).
- 1. Set |accountState| to the result of running the [=compute the connection status=] algorithm
- given |provider| and |account|.
- 1. If |accountState| is [=compute the connection status/disconnected=]:
+ 1. If [=compute the connection status=] of |account|, |provider| and |globalObject| is
+ [=compute the connection status/connected=], set |permission| to true.
+ 1. Otherwise:
1. Let |permission| be the result of running the [=request permission to sign-up=]
algorithm with |account|, |config|, |provider|, and |globalObject|.
1. Set |disclosureTextShown| to true.
- 1. Otherwise, set |permission| to true.
1. Wait until the [=user agent=]'s dialogs requesting for user choice or permission to be
closed, if any are created in the previous steps.
1. Assert: |account| is not null.
1. If |permission| is false, then return (failure, true).
1. Let |credential| be the result of running the [=fetch an identity assertion=] algorithm with
- |account|'s {{IdentityProviderAccount/id}}, |disclosureTextShown|, |provider|, |config|, and
- |globalObject|.
+ |account|'s {{IdentityProviderAccount/id}}, |disclosureTextShown|, |isAutoSelected|,
+ |provider|, |config|, and |globalObject|.
1. Return |credential|.
@@ -1022,51 +929,59 @@ or failure.
1. Set |rootUrl|'s [=url/scheme=] to |configUrl|'s [=url/scheme=].
1. Set |rootUrl|'s [=url/host=] to |configUrl|'s [=url/host=]'s [=host/registrable domain=].
1. Set |rootUrl|'s [=url/path=] to the
list «".well-known", "web-identity"».
- 1. Let |wellKnownRequest| be a new [=/request=] as follows:
-
- : [=request/URL=]
- :: |rootUrl|
- : [=request/client=]
- :: null
- : [=request/window=]
- :: "no-window"
- : [=request/service-workers mode=]
- :: "none"
- : [=request/destination=]
- :: "webidentity"
- : [=request/origin=]
- :: a unique [=opaque origin=]
- : [=request/header list=]
- :: a [=list=] containing a single [=header=] with [=header/name=] set to `Accept` and
- [=header/value=] set to `application/json`
- : [=request/referrer policy=]
- :: "no-referrer"
- : [=request/credentials mode=]
- :: "omit"
- : [=request/mode=]
- :: "no-cors"
-
- Issue: The spec is yet to be updated so that all
requests are created
- with [=request/mode=] set to "user-agent-no-cors". See the relevant
- [pull request](https://github.com/whatwg/fetch/pull/1533) for details.
-
1. Let |config|, |configInWellKnown| both be null.
- 1. [=Fetch request=] with |wellKnownRequest| and |globalObject|, and with
processResponseConsumeBody
- set to the following steps given a
response |response| and |responseBody|:
- 1. Let |json| be the result of [=extract the JSON fetch response=] from |response| and
- |responseBody|.
- 1. [=converted to an IDL value|Convert=] |json| to an {{IdentityProviderWellKnown}},
- |discovery|.
- 1. If one of the previous two steps threw an exception, or if the
- [=list/size=] of |discovery|["{{IdentityProviderWellKnown/provider_urls}}"] is
- greater than 1, set |configInWellKnown| to false.
-
- Issue: [relax](https://github.com/fedidcg/FedCM/issues/333) the size of the
- provider_urls array.
+ 1. Let |rpOrigin| be |globalObject|'s [=associated Document=]'s [=Document/origin=].
+ 1. If |rpOrigin| is not an [=opaque origin=], and |rootUrl|'s [=url/host=] is equal
+ to |rpOrigin|'s [=host/registrable domain=], and |rootUrl|'s [=url/scheme=] is
+ equal to |rpOrigin|'s [=origin/scheme=], set |configInWellKnown| to true.
- 1. Otherwise, set to |configInWellKnown| to true if
- |discovery|["{{IdentityProviderWellKnown/provider_urls}}"][0] [=string/is=] equal to
- |provider|'s {{IdentityProviderConfig/configURL}}, and to false otherwise.
+ Note: Because domain cookies are valid across an entire site, there is no privacy
+ benefit from doing the well-known check if the RP and IDP are in the same site.
+ 1. Otherwise:
+ 1. Let |wellKnownRequest| be a new [=/request=] as follows:
+
+ : [=request/URL=]
+ :: |rootUrl|
+ : [=request/client=]
+ :: null
+ : [=request/window=]
+ :: "no-window"
+ : [=request/service-workers mode=]
+ :: "none"
+ : [=request/destination=]
+ :: "webidentity"
+ : [=request/origin=]
+ :: a unique [=opaque origin=]
+ : [=request/header list=]
+ :: a [=list=] containing a single [=header=] with [=header/name=] set to `Accept` and
+ [=header/value=] set to `application/json`
+ : [=request/referrer policy=]
+ :: "no-referrer"
+ : [=request/credentials mode=]
+ :: "omit"
+ : [=request/mode=]
+ :: "no-cors"
+
+ Issue: The spec is yet to be updated so that all
requests are created
+ with [=request/mode=] set to "user-agent-no-cors". See the relevant
+ [pull request](https://github.com/whatwg/fetch/pull/1533) for details.
+
+ 1. [=Fetch request=] with |wellKnownRequest| and |globalObject|, and with
processResponseConsumeBody
+ set to the following steps given a
response |response| and |responseBody|:
+ 1. Let |json| be the result of [=extract the JSON fetch response=] from |response| and
+ |responseBody|.
+ 1. [=converted to an IDL value|Convert=] |json| to an {{IdentityProviderWellKnown}},
+ |discovery|.
+ 1. If one of the previous two steps threw an exception, or if the
+ [=list/size=] of |discovery|["{{IdentityProviderWellKnown/provider_urls}}"] is
+ greater than 1, set |configInWellKnown| to false.
+
+ Issue: [relax](https://github.com/fedidcg/FedCM/issues/333) the size of the
+ provider_urls array.
+
+ 1. Otherwise, set to |configInWellKnown| to true if
+ |discovery|["{{IdentityProviderWellKnown/provider_urls}}"][0] [=string/is=] equal to
+ |provider|'s {{IdentityProviderConfig/configURL}}, and to false otherwise.
1. Let |configRequest| be a new
request as follows:
@@ -1148,15 +1063,15 @@ dictionary IdentityProviderAPIConfig {
-### Fetch the accounts list ### {#fetch-accounts-list}
+### Fetch the accounts ### {#fetch-accounts}
-The
fetch the accounts list algorithm fetches the [=accounts list endpoint=] to determine the
+The
fetch the accounts algorithm fetches the [=accounts endpoint=] to determine the
list of [=IDP=] accounts that the user is signed in to, so that the user agent can later show the
FedCM UI to the user.
-To
fetch the accounts list given an {{IdentityProviderAPIConfig}} |config|, an
+To
fetch the accounts given an {{IdentityProviderAPIConfig}} |config|, an
{{IdentityProviderRequestOptions}} |provider|, and |globalObject|, run the following steps. This
returns an {{IdentityProviderAccountList}}.
1. Let |accountsUrl| be the result of [=computing the manifest URL=] given |provider|,
@@ -1277,9 +1192,9 @@ the token that will be provided to the [=RP=].
To
fetch an identity assertion given a {{USVString}}
- |accountId|, a boolean |disclosureTextShown|, an {{IdentityProviderRequestOptions}} |provider|,
- an {{IdentityProviderAPIConfig}} |config|, and |globalObject|, run the following steps. This
- returns an {{IdentityCredential}} or failure.
+ |accountId|, a boolean |disclosureTextShown|, a boolean |isAutoSelected|, an
+ {{IdentityProviderRequestOptions}} |provider|, an {{IdentityProviderAPIConfig}} |config|,
+ and |globalObject|, run the following steps. This returns an {{IdentityCredential}} or failure.
1. Let |tokenUrl| be the result of [=computing the manifest URL=] given |provider|,
|config|["{{IdentityProviderAPIConfig/id_assertion_endpoint}}"], and |globalObject|.
1. If |tokenUrl| is failure, return failure.
@@ -1288,6 +1203,7 @@ To
fetch an identity assertion given a {{USVString}}
1. ("nonce", |provider|'s {{IdentityProviderRequestOptions/nonce}})
1. ("account_id", |accountId|)
1. ("disclosure_text_shown", |disclosureTextShown|)
+ 1. ("is_auto_selected", |isAutoSelected|)
1. Let |request| be a new
request as follows:
: [=request/url=]
@@ -1314,11 +1230,7 @@ To
fetch an identity assertion given a {{USVString}}
: [=request/credentials mode=]
:: "include"
: [=request/mode=]
- :: "no-cors"
-
- Issue: The spec is yet to be updated so that all
requests are created
- with [=request/mode=] set to "user-agent-no-cors". See the relevant
- [pull request](https://github.com/whatwg/fetch/pull/1533) for details.
+ :: "cors"
1. Let |credential| be null.
1. [=Fetch request=] with |request| and |globalObject|, and with
processResponseConsumeBody
@@ -1331,6 +1243,8 @@ To
fetch an identity assertion given a {{USVString}}
1. Let |credential| be a new {{IdentityCredential}} given |globalObject|'s
realm.
1. Set |credential|'s {{IdentityCredential/token}} to |token|.
+ 1. Set |credential|'s {{IdentityCredential/isAutoSelected}} to
+ |isAutoSelected|.
1. Wait for |credential| to be set.
1. Return |credential|.
@@ -1515,10 +1429,10 @@ success or failure.
1. Assert: |loginUrl| is not failure (the [=user agent=] has previously checked that
|config|.{{IdentityProviderAPIConfig/login_url}} is a valid URL).
1. Let |queryList| be a new [=list=].
- 1. If |provider|'s {{IdentityProviderConfig/loginHint}} is not empty, [=list/append=]
- ("login_hint", {{IdentityProviderConfig/loginHint}}) to |queryList|.
- 1. If |provider|'s {{IdentityProviderConfig/domainHint}} is not empty, [=list/append=]
- ("domain_hint", {{IdentityProviderConfig/domainHint}}) to |queryList|.
+ 1. If |provider|'s {{IdentityProviderRequestOptions/loginHint}} is not empty, [=list/append=]
+ ("login_hint", {{IdentityProviderRequestOptions/loginHint}}) to |queryList|.
+ 1. If |provider|'s {{IdentityProviderRequestOptions/domainHint}} is not empty, [=list/append=]
+ ("domain_hint", {{IdentityProviderRequestOptions/domainHint}}) to |queryList|.
1. If |queryList| is not [=list/empty=]:
1. Let |queryParameters| be the result of the [=urlencoded serializer=] with |queryList|.
1. If |loginUrl|'s [=url/query=] is not null or empty, prepend "&" to |queryParameters|.
@@ -1536,8 +1450,8 @@ success or failure.
with the [=/origin=] of the {{IdentityProviderAPIConfig/login_url}}.
Note: The IDP login flow may set this value to logged-in using
- either the [[#login-status-javascript|JavaScript]] or
- [[#login-status-http|HTTP header]] API during the login
+ either the [login-status.html#login-status-javascript](JavaScript) or
+ [login-status.html#login-status-http](HTTP header) API during the login
flow. It is also possible that this change happened in
a different browsing context.
1. If |loginStatus| is [=logged-in=], return success.
@@ -1581,7 +1495,7 @@ An {{IdentityUserInfo}} represents user account information from a user. This in
to the [=IDP=] once the user has already used the FedCM API to login in the [=RP=]. That is, it is
exposed when there exists an account |account| such that the [=connected accounts set=] [=list/contains=]
the triple ([=RP=], [=IDP=], |account|). The information matches what is received from the
-
accounts list endpoint. The [=IDP=] can obtain this information by invoking the
+
accounts endpoint. The [=IDP=] can obtain this information by invoking the
{{IdentityProvider/getUserInfo()}} static method from an iframe matching the [=/origin=] of its
{{IdentityProviderConfig/configURL}}.
@@ -1611,9 +1525,9 @@ When invoking the {{IdentityProvider/getUserInfo()}} method given an {{IdentityP
1. Let |document| be |globalObject|'s [=associated Document=].
1. If |document| is not [=allowed to use=] the [=identity-credentials-get=]
[=policy-controlled feature=], throw a "{{NotAllowedError}}" {{DOMException}}.
- 1. If there does not exist an account |account| such that [=compute the connection status=] of
- |provider|, |account|, and |globalObject| returns
- [=compute the connection status/connected=], then throw a new "{{NetworkError}}"
+ 1. If there does not exist an account |account| such that [=connected accounts set=]
+ [=list/contains=] the result of [=compute the connected account key=] given |account|,
+ |provider|, and |globalObject|, then [=reject=] |promise| with a "{{NetworkError}}"
{{DOMException}}. This check can be performed by iterating over the
[=connected accounts set=] or by keeping a separate data structure to make this lookup fast.
1. Let |configUrl| be the result of running [=parse url=] with |provider|'s
@@ -1633,10 +1547,10 @@ When invoking the {{IdentityProvider/getUserInfo()}} method given an {{IdentityP
|globalObject|.
1. If |config| is failure, [=reject=] |promise| with a new "{{NetworkError}}"
{{DOMException}}.
- 1. Let |accountsList| be the result of [=fetch the accounts list=] with |config|, |provider|,
+ 1. Let |accountsList| be the result of [=fetch the accounts=] with |config|, |provider|,
and |globalObject|.
- 1. Let |isReturningAccount| be a new [=list=] of the same length as |accountsList|, with all
- values initially set to false.
+ 1. Let |isEligibleForAutoReauthentication| be a new [=list=] of the same length as |accountsList|,
+ with all values initially set to false.
1. For each |i| from 0 to the length of |accountsList| minus 1:
1. Let |account| be |accountsList|[|i|].
1. If |account|["{{IdentityProviderAccount/approved_clients}}"] is not empty and it does not
@@ -1647,10 +1561,10 @@ When invoking the {{IdentityProvider/getUserInfo()}} method given an {{IdentityP
account out of band.
1. [=Compute the connection status=] of |provider|, |account|, and |globalObject|. If the
- result is [=compute the connection status/connected=], set |isReturningAccount|[|i|] to
- true.
- 1. If |isReturningAccount| does not [=list/contain=] true, [=reject=] |promise| with a new
- "{{NetworkError}}" {{DOMException}}.
+ result is [=compute the connection status/connected=], set
+ |isEligibleForAutoReauthentication|[|i|] to true.
+ 1. If |isEligibleForAutoReauthentication| does not [=list/contain=] true, [=reject=] |promise| with
+ a new "{{NetworkError}}" {{DOMException}}.
1. Let |userInfoList| be a new [=list=].
1. Let |notReturningUserInfos| be a new [=list=].
1. For each |i| from 0 to the length of |accountsList| minus 1:
@@ -1665,7 +1579,7 @@ When invoking the {{IdentityProvider/getUserInfo()}} method given an {{IdentityP
:: |account|["{{IdentityProviderAccount/given_name}}"]
: {{IdentityUserInfo/picture}}
:: |account|["{{IdentityProviderAccount/picture}}"]
- 1. If |isReturningAccount|[|i|], [=list/append=] |userInfo| to |userInfoList|.
+ 1. If |isEligibleForAutoReauthentication|[|i|], [=list/append=] |userInfo| to |userInfoList|.
1. Otherwise, [=list/append=] |userInfo| to |notReturningUserInfos|.
1. [=list/Extend=] |userInfo| with |notReturningUserInfos|.
1. [=Resolve=] a new {{Promise}} with |userInfoList|.
@@ -1692,7 +1606,7 @@ to execute these in such a way that it does not allow the user to be tracked (by
impersonating an [=IDP=]) on to the site using FedCM. The following table has information about the
network requests performed:
-
+
Endpoint | cookies | client_id | origin |
manifests | no | no | no |
accounts_endpoint | yes | no | no |
@@ -1848,12 +1762,12 @@ For example:
-## Accounts list endpoint ## {#idp-api-accounts-endpoint}
+## Accounts endpoint ## {#idp-api-accounts-endpoint}
-The accounts list endpoint provides the list of accounts the user has at the [=IDP=].
+The accounts endpoint provides the list of accounts the user has at the [=IDP=].
-The [=accounts list endpoint=] is fetched in the [=fetch the accounts list=] algorithm:
+The [=accounts endpoint=] is fetched in the [=fetch the accounts=] algorithm:
(a) **with** [=IDP=] cookies,
(b) **with** the Sec-Fetch-Dest header set to `webidentity`,
@@ -1898,7 +1812,7 @@ Every {{IdentityProviderAccount}} is expected to have members with the following
matching a given value is shown to the user.
: domain_hints
:: A list of strings which correspond to all of the domain hints which match with this account.
- An [=RP=] can use the {{IdentityProviderConfig/domainHint}} to request that only an account
+ An [=RP=] can use the {{IdentityProviderRequestOptions/domainHint}} to request that only an account
matching a given value or containing some domain hint is shown to the user.
@@ -2034,8 +1948,6 @@ the Origin header value is represented by the
[=IDP=]-specific, the [=user agent=] cannot perform this check.
-Note: An [=IDP=] should validate the nonce, if present, to prevent CSRF-style attacks.
-
The response body must be a JSON object that can be [=converted to an IDL value|converted=] to an {{IdentityProviderToken}} without an exception.
Every {{IdentityProviderToken}} is expected to have members with the following semantics:
@@ -2085,7 +1997,7 @@ method:
(b) **with** [=IDP=] cookies,
(c) **with** the [=RP=]'s origin in the Origin header,
(d) **with** the Sec-Fetch-Dest header set to `webidentity`,
-(e) **without** following [[RFC9110#section-10.2.2|HTTP redirects]], and
+(e) **without** following [[RFC9110#field.location|HTTP redirects]], and
(f) in "cors" [=request/mode=].
It will also contain the following in the request body `application/x-www-form-urlencoded`:
@@ -2343,8 +2255,8 @@ The [=remote end steps=] are:
if present
1. `idpConfigUrl` set to the {{IdentityProviderConfig/configURL}} of the
IDP this account belongs to
- 1. `loginState` to `"SignUp"` if |accountState| is [=compute the connection status/disconnected=]
- and `"SignIn"` otherwise
+ 1. `loginState` to `"SignUp"` if |accountState| is
+ [=compute the connection status/disconnected=] and `"SignIn"` otherwise
1. `termsOfServiceUrl` to the {{IdentityProviderClientMetadata/terms_of_service_url}}
if one was provided and the `loginState` is `"SignUp"`, otherwise {{undefined}}
1. `privacyPolicyUrl` to the {{IdentityProviderClientMetadata/privacy_policy_url}}
@@ -2372,8 +2284,8 @@ The [=remote end steps=] are:
Note: This command lets automation verify that the
- [context api](https://github.com/fedidcg/FedCM/blob/main/proposals/context-api.md)
- was applied properly
+ [context api](#dom-identitycredentialrequestoptions-context)
+ was applied properly
The [=remote end steps=] are:
@@ -2519,6 +2431,16 @@ credentialed requests it receives, which ensures that the request was initiated
based on the FedCM API. A malicious actor cannot spam FedCM API calls, so this is sufficient
protection for the new [=IDP=] endpoints.
+
+## CORS Header ## {#sec-cors-header}
+
+
+The FedCM API allows the response from the [=identity assertion endpoint=] to be shared to the
+[=RP=]. Because of this, we impose the requirement that the [=IDP=] explicitly consents to this
+sharing taking place by using the "cors" [=request/mode=] when fetching this endpoint. This also
+helps with servers that may accidentally ignore the Sec-Fetch-Dest: they cannot
+ignore CORS, as without it the fetch will fail.
+
## Browser Surface Impersonation ## {#browser-surface-impersonation}
@@ -2608,7 +2530,7 @@ origin of the fetched URLs.
or referrer. Thus, anyone could perform this fetch, and the information contained therein
is considered public.
-* The [=accounts list endpoint=] fetch can't be used to track users because it is performed with cookies from the
+* The [=accounts endpoint=] fetch can't be used to track users because it is performed with cookies from the
[=IDP=] but, importantly, without the {{id_assertion_endpoint_request/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
@@ -2928,3 +2850,44 @@ Note: write down the Acknowledgements section.
}
}
+
+
+# FPWD Issues # {#openissues}
+
+Note: The WG has labeled the following issues as critical open issues that must be formally addressed before publication of a Candidate Recommendation.
+
+
+