Skip to content

Commit 843eb51

Browse files
pottisSuresh Potti
andauthored
FedCM Object Token Enhancement (#771)
* Made changes to incorporate token new format * Addressed review comments * removed unwanted file * minor edit * minor edit * minor edit * minor edit * addressed review comments * minor comments * addressd review comment * minor correction --------- Co-authored-by: Suresh Potti <[email protected]>
1 parent b8e3ce8 commit 843eb51

File tree

1 file changed

+73
-16
lines changed

1 file changed

+73
-16
lines changed

‎spec/index.bs‎

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ could be implemented.
155155
// Prompt the user to select an account from the IDP to use for
156156
// federated login within the RP. If resolved successfully, the Promise
157157
// returns an IdentityCredential object from which the |token| can be
158-
// extracted. This is an opaque string passed from the IDP to the RP.
158+
// extracted. This is passed from the IDP to the RP and can be any type of value.
159159
let token = await navigator.credentials.get({
160160
identity: {
161161
providers: [{
@@ -164,6 +164,14 @@ could be implemented.
164164
}]
165165
}
166166
});
167+
168+
// Handle the token - it could be a string or JSON object
169+
let token = credential.token;
170+
if (typeof token === 'object' && token !== null) {
171+
// Handle structured token (e.g., OAuth response)
172+
} else if (typeof token === 'string') {
173+
// Handle string token (e.g., JWT)
174+
}
167175
} catch(e) {
168176
// The FedCM call was not successful.
169177
}
@@ -453,7 +461,7 @@ This specification introduces a new type of {{Credential}}, called an {{Identity
453461
[Exposed=Window, SecureContext]
454462
interface IdentityCredential : Credential {
455463
static Promise&lt;undefined&gt; disconnect(IdentityCredentialDisconnectOptions options);
456-
readonly attribute USVString? token;
464+
readonly attribute any token;
457465
readonly attribute boolean isAutoSelected;
458466
readonly attribute USVString configURL;
459467
};
@@ -465,6 +473,8 @@ This specification introduces a new type of {{Credential}}, called an {{Identity
465473
: <b>{{IdentityCredential/token}}</b>
466474
:: The {{IdentityCredential/token}}'s attribute getter returns the value it is set to.
467475
It represents the minted {{IdentityAssertionResponse/token}} provided by the [=IDP=].
476+
The type returned depends on what the [=IDP=] provides in its assertion endpoint response.
477+
[=RP=] MUST check the type of the token before processing it.
468478
: <b>{{IdentityCredential/isAutoSelected}}</b>
469479
:: {{IdentityCredential/isAutoSelected}}'s attribute getter returns the value it is
470480
set to. It represents whether the user's identity credential was automatically selected when
@@ -1514,11 +1524,11 @@ To <dfn>fetch an identity assertion</dfn> given a {{USVString}}
15141524
1. Set |credential| to the result of [=create an IdentityCredentialError=] with {} and
15151525
|globalObject|.
15161526
1. The user agent MAY set |credential|'s {{IdentityCredentialError/error}} based on
1517-
|response|'s [=response/status=]. For example, if the [=response/status=] is 500, it
1518-
could set it to "server_error", and if the [=response/status=] is 503, it could set
1527+
|response|'s [=response/status=]. For example, if the [=response/status=] is `500`, it
1528+
could set it to "server_error", and if the [=response/status=] is `503`, it could set
15191529
it to "temporarily_unavailable".
1520-
1. Otherwise, if {{IdentityAssertionResponse/token}} was specified, let |tokenString|
1521-
be |token|'s {{IdentityAssertionResponse/token}}.
1530+
1. Otherwise, if {{IdentityAssertionResponse/token}} was specified:
1531+
1. Let |tokenValue| be |token|'s {{IdentityAssertionResponse/token}}.
15221532
1. Otherwise, if {{IdentityAssertionResponse/continue_on}} was specified, run these steps
15231533
[=in parallel=]:
15241534
1. Let |continueOnUrl| be the result of running [=parse url=] with |token|'s
@@ -1528,19 +1538,19 @@ To <dfn>fetch an identity assertion</dfn> given a {{USVString}}
15281538
to failure and return.
15291539
1. Let |tokenPair| be the result of [=show a continuation dialog=] with |continueOnUrl|.
15301540
1. If |tokenPair| is failure, set |credential| to failure and return.
1531-
1. Let |tokenString| be the first entry of |tokenPair|.
1541+
1. Let |tokenValue| be the first entry of |tokenPair|.
15321542
1. If the second entry of |tokenPair| is not null, set |accountId| to that second entry.
15331543
1. Otherwise, set |credential| to a the result of [=create an IdentityCredentialError=] with
15341544
{} and |globalObject|,
1535-
1. Wait for |tokenString| or |credential| to be set.
1545+
1. Wait for |tokenValue| or |credential| to be set.
15361546
1. If |credential| is set:
15371547
1. Assert that |credential| is set to failure.
15381548
1. Return |credential|.
15391549
1. [=Create a connection between the RP and the IdP account=] with |provider|, |accountId|, and
15401550
|globalObject|.
15411551
1. Let |credential| be a new {{IdentityCredential}} given |globalObject|'s
15421552
<a for="global object">realm</a>.
1543-
1. Set |credential|'s {{IdentityCredential/token}} to |tokenString|.
1553+
1. Set |credential|'s {{IdentityCredential/token}} to |tokenValue|.
15441554
1. Set |credential|'s {{IdentityCredential/isAutoSelected}} to
15451555
|isAutoSelected|.
15461556
1. Set |credential|'s {{IdentityCredential/configURL}} to |provider|'s
@@ -1580,7 +1590,7 @@ An extension may add the following steps after the [=fetch identity assertion/cr
15801590

15811591
<pre class="idl">
15821592
dictionary IdentityAssertionResponse {
1583-
USVString token;
1593+
any token;
15841594
USVString continue_on;
15851595
IdentityCredentialErrorInit error;
15861596
};
@@ -1812,7 +1822,7 @@ success or failure.
18121822

18131823
<div algorithm>
18141824
To <dfn>show a continuation dialog</dfn> given a |continueOnUrl|, run the
1815-
following steps. This returns a failure or a tuple (string, string?) (a token
1825+
following steps. This returns a failure or a tuple (any, string?) (a token
18161826
and an optional account ID).
18171827
1. Assert: these steps are running [=in parallel=].
18181828
1. [=Create a fresh top-level traversable=] with |continueOnUrl|.
@@ -1828,11 +1838,11 @@ and an optional account ID).
18281838
* {{IdentityProvider}}.{{IdentityProvider/resolve()}} is called in
18291839
the context of this new traversable.
18301840
1. Close the traversable.
1831-
1. Let |token| be the token that was passed to that resolve call.
1841+
1. Let |tokenValue| be the token that was passed to that resolve call.
18321842
1. If {{IdentityResolveOptions/accountId}} was specified in the
18331843
resolve call, let |accountId| be that account ID.
18341844
1. Otherwise, let |accountId| be null.
1835-
1. Return (|token|, |accountId|).
1845+
1. Return (|tokenValue|, |accountId|).
18361846

18371847
</div>
18381848

@@ -1870,7 +1880,7 @@ This specification introduces the {{IdentityUserInfo}} dictionary as well as the
18701880

18711881
[Exposed=Window, SecureContext] interface IdentityProvider {
18721882
static undefined close();
1873-
static Promise&lt;undefined&gt; resolve(DOMString token, optional IdentityResolveOptions options = {});
1883+
static Promise&lt;undefined&gt; resolve(any token, optional IdentityResolveOptions options = {});
18741884
static Promise&lt;sequence&lt;IdentityUserInfo&gt;&gt; getUserInfo(IdentityProviderConfig config);
18751885
};
18761886
</pre>
@@ -2425,7 +2435,10 @@ Every {{IdentityAssertionResponse}} is expected to have members with the followi
24252435

24262436
<dl dfn-type="dict-member" dfn-for="IdentityAssertionResponse">
24272437
: <dfn>token</dfn>
2428-
:: The resulting token.
2438+
:: The resulting token. The value is of type <a href="https://webidl.spec.whatwg.org/#idl-any">`any`</a>, allowing
2439+
[=IDPs=] to return tokens in various formats (string, object, etc.).
2440+
See the examples at the end of [[#idp-api-id-assertion-endpoint]] for both string
2441+
and object token formats.
24292442
: <dfn>continue_on</dfn>
24302443
:: A URL that the user agent will open in a popup to finish the authentication process.
24312444
: <dfn>error</dfn>
@@ -2450,7 +2463,7 @@ Portability is left entirely up to [=IDPs=], who can choose
24502463
between a variety of different mechanisms to accomplish it
24512464
(e.g. [OIDC's Account Porting](https://openid.net/specs/openid-connect-account-porting-1_0.html)).
24522465

2453-
For example:
2466+
Example (string token):
24542467

24552468
<div class=example>
24562469
```json
@@ -2460,6 +2473,16 @@ For example:
24602473
```
24612474
</div>
24622475

2476+
Example (JSON object token):
2477+
2478+
<div class=example>
2479+
```json
2480+
{
2481+
{ "token" : { "access_token": "eyJC...J9.eyJzdWTE2...MjM5MDIyfQ.SflV_adQssw....5c", "token_type": "Bearer", "expires_in": 3600, "scope": "openid profile email", "refresh_token": "eyJC...refresh...token" } }
2482+
}
2483+
```
2484+
</div>
2485+
24632486
<!-- ============================================================ -->
24642487
## Disconnect endpoint ## {#idp-api-disconnect-endpoint}
24652488
<!-- ============================================================ -->
@@ -2924,6 +2947,27 @@ distinguishing browser-initiated FedCM flows from arbitrary requests.
29242947
[=IDP=] and [=RP=] endpoints are implemented correctly and do not contain vulnerabilities that could
29252948
allow an attacker to bypass the FedCM flow or extract sensitive data.
29262949

2950+
<!-- ============================================================ -->
2951+
### Token Format and Validation ### {#token-format-validation}
2952+
<!-- ============================================================ -->
2953+
2954+
**Consideration**
2955+
2956+
The FedCM API supports flexible token formats, allowing [=IDPs=] to return tokens in various forms.
2957+
[=RPs=] must be prepared to handle different token structures as agreed upon with their [=IDP=]
2958+
partners. The token content remains opaque to the user agent.
2959+
2960+
**Recommendations**
2961+
2962+
1. [=RPs=] should implement robust token parsing logic that can handle the specific format agreed
2963+
upon with their [=IDP=] partners.
2964+
1. [=RPs=] should validate tokens according to the security requirements and format specifications
2965+
established with their [=IDP=].
2966+
1. [=IDPs=] should clearly document their token format and structure to help [=RPs=] implement
2967+
proper validation.
2968+
1. [=IDPs=] should ensure their token format is consistent and follows their documented
2969+
specification.
2970+
29272971
<!-- ============================================================ -->
29282972
## Threats and Attacks ## {#security-threats-aattacks}
29292973
<!-- ============================================================ -->
@@ -3473,6 +3517,19 @@ These schemes have not been adopted by this specification.
34733517
</pre>
34743518
</div>
34753519

3520+
<!-- ============================================================ -->
3521+
### Token Content Privacy ### {#token-content-privacy}
3522+
<!-- ============================================================ -->
3523+
3524+
The FedCM API treats token content as opaque data, regardless of type.
3525+
This design ensures:
3526+
3527+
1. The [=user agent=] does not semantically interpret or validate the meaning of token contents, but
3528+
may inspect their type and structure for proper handling, while maintaining the privacy of the
3529+
authentication data.
3530+
1. The token format flexibility does not introduce new privacy risks.
3531+
1. [=IDPs=] have flexibility in token design without compromising user privacy.
3532+
34763533
<!-- ====================================================================== -->
34773534
# Extensibility # {#extensibility}
34783535
<!-- ====================================================================== -->

0 commit comments

Comments
 (0)