From 01d8942a9f0979d1d1abbfb796ced8a5b12cef2d Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Wed, 2 Oct 2024 17:15:40 -0400 Subject: [PATCH 1/6] Specify the continuation API Bug: w3c-fedid/custom-requests#1 --- spec/index.bs | 53 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index b2462419..4f1b7650 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -1240,9 +1240,25 @@ To fetch an identity assertion given a {{USVString}} 1. [=converted to an IDL value|Convert=] |json| to an {{IdentityProviderToken}}, |token|. 1. If one of the previous two steps threw an exception, set |credential| to failure and return. + 1. If neither {{IdentityProviderToken/token}} nor {{IdentityProviderToken/continue_on}} was + specified, set |credential| to failure and return. + 1. If {{IdentityProviderToken/token}} was not specified but + {{IdentityProviderToken/continue_on}} was specified: + 1. Let |continueOnUrl| be the result of running [=parse url=] with |token|'s + {{IdentityProviderToken/continue_on}} and |globalObject|. + 1. If |continueOnUrl| is failure, set |credential| to failure and return. + 1. If |continueOnUrl| is not [=same origin=] with |tokenUrl|, set |credential| + to failure and return. + 1. Let |tokenPair| be the result of [=show a continuation dialog=] with |continueOnUrl|. + 1. If |tokenPair| is failure, set |credential| to failure and return. + 1. Let |tokenString| be the first entry of |tokenPair|. + 1. If the second entry of |tokenPair| is not null, set |accountId| to that second entry. + 1. Otherwise, let |tokenString| be |token|'s {{IdentityProviderToken/token}}. + 1. [=Create a connection between the RP and the IdP account=] with |provider|, |accountId|, and + |globalObject|. 1. Let |credential| be a new {{IdentityCredential}} given |globalObject|'s realm. - 1. Set |credential|'s {{IdentityCredential/token}} to |token|. + 1. Set |credential|'s {{IdentityCredential/token}} to |tokenString|. 1. Set |credential|'s {{IdentityCredential/isAutoSelected}} to |isAutoSelected|. 1. Wait for |credential| to be set. @@ -1251,7 +1267,8 @@ To fetch an identity assertion given a {{USVString}} dictionary IdentityProviderToken { - required USVString token; + USVString token; + USVString continue_on; }; @@ -1293,8 +1310,6 @@ an {{IdentityProviderAPIConfig}} |config|, an {{IdentityProviderRequestOptions}} 1. The user agent MAY use the {{IdentityCredentialRequestOptions/context}} to customize the dialog shown. 1. If the user does not grant permission, return false. - 1. [=Create a connection between the RP and the IdP account=] with |provider|, |account|, and - |globalObject|. 1. Return true. @@ -1458,6 +1473,31 @@ success or failure. 1. Otherwise, return failure. +
+To show a continuation dialog given a |continueOnUrl|, run the +following steps. This returns a failure or a tuple (string, string?) (a token +and an optional account ID). + 1. Assert: these steps are running [=in parallel=]. + 1. [=Create a fresh top-level traversable=] with |continueOnUrl|. + 1. The user agent MAY [=set up browsing context features=] or otherwise + affect the presentation of this traversable in an implementation-defined + way. + 1. Wait for one of the following conditions: + * The user closes the browsing context: return failure. + * {{IdentityProvider}}.{{IdentityProvider/close}} is called in the + context of this new traversable: + 1. Close the traversable. + 1. Return failure. + * {{IdentityProvider}}.{{IdentityProvider/resolve()}} is called in + the context of this new traversable. + 1. Close the traversable. + 1. Let |token| be the token that was passed to that resolve call. + 1. If {{IdentityResolveOptions/accountId}} was specified in the + resolve call, let |accountId| be that account ID. + 1. Otherwise, let |accountId| be null. + 1. Return (|token|, |accountId|). + +
## The IdentityProvider Interface ## {#browser-api-identity-provider-interface} @@ -1473,8 +1513,13 @@ This specification introduces the {{IdentityUserInfo}} dictionary as well as the USVString picture; }; + dictionary IdentityResolveOptions { + USVString accountId; + }; + [Exposed=Window, SecureContext] interface IdentityProvider { static undefined close(); + static undefined resolve(DOMString token, optional IdentityResolveOptions options = {}); static Promise<sequence<IdentityUserInfo>> getUserInfo(IdentityProviderConfig config); }; From 2ceb1ddd7e16b35988dfb8efb198c824e2fe05e3 Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Mon, 7 Oct 2024 16:32:59 -0400 Subject: [PATCH 2/6] swap order --- spec/index.bs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index 4f1b7650..07410d90 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -1242,8 +1242,9 @@ To fetch an identity assertion given a {{USVString}} and return. 1. If neither {{IdentityProviderToken/token}} nor {{IdentityProviderToken/continue_on}} was specified, set |credential| to failure and return. - 1. If {{IdentityProviderToken/token}} was not specified but - {{IdentityProviderToken/continue_on}} was specified: + 1. If {{IdentityProviderToken/token}} was specified, let |tokenString| + be |token|'s {{IdentityProviderToken/token}}. + 1. Otherwise, if {{IdentityProviderToken/continue_on}} was specified: 1. Let |continueOnUrl| be the result of running [=parse url=] with |token|'s {{IdentityProviderToken/continue_on}} and |globalObject|. 1. If |continueOnUrl| is failure, set |credential| to failure and return. @@ -1253,7 +1254,6 @@ To fetch an identity assertion given a {{USVString}} 1. If |tokenPair| is failure, set |credential| to failure and return. 1. Let |tokenString| be the first entry of |tokenPair|. 1. If the second entry of |tokenPair| is not null, set |accountId| to that second entry. - 1. Otherwise, let |tokenString| be |token|'s {{IdentityProviderToken/token}}. 1. [=Create a connection between the RP and the IdP account=] with |provider|, |accountId|, and |globalObject|. 1. Let |credential| be a new {{IdentityCredential}} given |globalObject|'s From 39d9fe944373c415d8c4f5e74467de3d9dc44ea2 Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Mon, 7 Oct 2024 16:35:02 -0400 Subject: [PATCH 3/6] first --- spec/index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/index.bs b/spec/index.bs index 07410d90..d3c06803 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -1482,7 +1482,7 @@ and an optional account ID). 1. The user agent MAY [=set up browsing context features=] or otherwise affect the presentation of this traversable in an implementation-defined way. - 1. Wait for one of the following conditions: + 1. Wait for the first occurence of one of the following conditions: * The user closes the browsing context: return failure. * {{IdentityProvider}}.{{IdentityProvider/close}} is called in the context of this new traversable: From 7be08f8cdc313b4c54e86de6f8ee7d226fb95eb1 Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Tue, 12 Nov 2024 12:18:28 -0500 Subject: [PATCH 4/6] rename and in parallel --- spec/index.bs | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index d3c06803..71e887f0 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -451,7 +451,7 @@ This specification introduces a new type of {{Credential}}, called an {{Identity :: The {{Credential/id}}'s attribute getter returns the empty string. : {{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=]. + It represents the minted {{IdentityAssertionResponse/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 @@ -663,8 +663,8 @@ dictionary IdentityProviderRequestOptions : IdentityProviderConfig { :: The {{id_assertion_endpoint_request/client_id}} provided to the [=RP=] out of band by the [=IDP=] : {{IdentityProviderRequestOptions/nonce}} :: A random number of the choice of the [=RP=]. It is generally used to associate a client - session with a {{IdentityProviderToken/token}} and to mitigate replay attacks. Therefore, this value should have - sufficient entropy such that it would be hard to guess. + session with a {{IdentityAssertionResponse/token}} and to mitigate replay attacks. + Therefore, this value should have sufficient entropy such that it would be hard to guess. : {{IdentityProviderRequestOptions/loginHint}} :: A string representing the login hint corresponding to an account which the RP wants the user agent to show to the user. If provided, the user agent will not show accounts which do not @@ -1237,16 +1237,17 @@ To fetch an identity assertion given a {{USVString}} 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 {{IdentityProviderToken}}, |token|. + 1. [=converted to an IDL value|Convert=] |json| to an {{IdentityAssertionResponse}}, |token|. 1. If one of the previous two steps threw an exception, set |credential| to failure and return. - 1. If neither {{IdentityProviderToken/token}} nor {{IdentityProviderToken/continue_on}} was - specified, set |credential| to failure and return. - 1. If {{IdentityProviderToken/token}} was specified, let |tokenString| - be |token|'s {{IdentityProviderToken/token}}. - 1. Otherwise, if {{IdentityProviderToken/continue_on}} was specified: + 1. If neither {{IdentityAssertionResponse/token}} nor + {{IdentityAssertionResponse/continue_on}} was specified, set |credential| to failure + and return. + 1. If {{IdentityAssertionResponse/token}} was specified, let |tokenString| + be |token|'s {{IdentityAssertionResponse/token}}. + 1. Otherwise, run these steps [=in parallel=]: 1. Let |continueOnUrl| be the result of running [=parse url=] with |token|'s - {{IdentityProviderToken/continue_on}} and |globalObject|. + {{IdentityAssertionResponse/continue_on}} and |globalObject|. 1. If |continueOnUrl| is failure, set |credential| to failure and return. 1. If |continueOnUrl| is not [=same origin=] with |tokenUrl|, set |credential| to failure and return. @@ -1254,6 +1255,7 @@ To fetch an identity assertion given a {{USVString}} 1. If |tokenPair| is failure, set |credential| to failure and return. 1. Let |tokenString| be the first entry of |tokenPair|. 1. If the second entry of |tokenPair| is not null, set |accountId| to that second entry. + 1. Wait for |tokenString| to be set if necessary. 1. [=Create a connection between the RP and the IdP account=] with |provider|, |accountId|, and |globalObject|. 1. Let |credential| be a new {{IdentityCredential}} given |globalObject|'s @@ -1266,7 +1268,7 @@ To fetch an identity assertion given a {{USVString}} -dictionary IdentityProviderToken { +dictionary IdentityAssertionResponse { USVString token; USVString continue_on; }; @@ -1985,22 +1987,26 @@ the <a http-header>Origin</a> header value is represented by the [=IDP=]-specific, the [=user agent=] cannot perform this check. </div> -The response body must be a JSON object that can be [=converted to an IDL value|converted=] to an {{IdentityProviderToken}} without an exception. +The response body must be a JSON object that can be [=converted to an IDL value|converted=] to an {{IdentityAssertionResponse}} without an exception. -Every {{IdentityProviderToken}} is expected to have members with the following semantics: +Every {{IdentityAssertionResponse}} is expected to have members with the following semantics: -<dl dfn-type="dict-member" dfn-for="IdentityProviderToken"> +<dl dfn-type="dict-member" dfn-for="IdentityAssertionResponse"> : <dfn>token</dfn> :: The resulting token. + : <dfn>continue_on</dfn> + :: A URL that the user agent will open in a popup to finish the authentication process. </dl> -The content of the {{IdentityProviderToken/token}} is opaque to the user agent and can contain +Only one of `token` and `continue_on` should be specified. + +The content of the {{IdentityAssertionResponse/token}} is opaque to the user agent and can contain anything that the [=IDP=] would like to pass to the [=RP=] to facilitate the login. For this reason the [=RP=] -is expected to be the party responsible for validating the {{IdentityProviderToken/token}} passed -along from the [=IDP=] using the appropriate token validation -algorithms defined. One example of how this might be done is defined -in [[OIDC-Connect-Core#IDTokenValidation]]. +is expected to be the party responsible for validating the +{{IdentityAssertionResponse/token}} passed along from the [=IDP=] using the +appropriate token validation algorithms defined. One example of how this might +be done is defined in [[OIDC-Connect-Core#IDTokenValidation]]. NOTE: For [=IDPs=], it is worth considering how [portable](https://github.com/fedidcg/FedCM/issues/314) accounts are. From 92ec958a360068c872b4a5934a3b9ba3c5abfc5a Mon Sep 17 00:00:00 2001 From: Christian Biesinger <cbiesinger@chromium.org> Date: Mon, 18 Nov 2024 14:02:15 -0500 Subject: [PATCH 5/6] remove if necessary --- spec/index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/index.bs b/spec/index.bs index 71e887f0..7066beaa 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -1255,7 +1255,7 @@ To <dfn>fetch an identity assertion</dfn> given a {{USVString}} 1. If |tokenPair| is failure, set |credential| to failure and return. 1. Let |tokenString| be the first entry of |tokenPair|. 1. If the second entry of |tokenPair| is not null, set |accountId| to that second entry. - 1. Wait for |tokenString| to be set if necessary. + 1. Wait for |tokenString| to be set. 1. [=Create a connection between the RP and the IdP account=] with |provider|, |accountId|, and |globalObject|. 1. Let |credential| be a new {{IdentityCredential}} given |globalObject|'s From fc5d88590032c0482d6cf8dfbdee3df26cc105ab Mon Sep 17 00:00:00 2001 From: Christian Biesinger <cbiesinger@chromium.org> Date: Mon, 18 Nov 2024 14:08:47 -0500 Subject: [PATCH 6/6] failure --- spec/index.bs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/index.bs b/spec/index.bs index eec63077..ed519c2d 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -1279,7 +1279,10 @@ To <dfn>fetch an identity assertion</dfn> given a {{USVString}} 1. If |tokenPair| is failure, set |credential| to failure and return. 1. Let |tokenString| be the first entry of |tokenPair|. 1. If the second entry of |tokenPair| is not null, set |accountId| to that second entry. - 1. Wait for |tokenString| to be set. + 1. Wait for |tokenString| or |credential| to be set. + 1. If |credential| is set: + 1. Assert that |credential| is set to failure. + 1. Return |credential|. 1. [=Create a connection between the RP and the IdP account=] with |provider|, |accountId|, and |globalObject|. 1. Let |credential| be a new {{IdentityCredential}} given |globalObject|'s