Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the IDP sign-in status API to the spec #436

Merged
merged 47 commits into from
Oct 13, 2023
Merged
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
e2f48cc
Add the IDP sign-in status API to the spec
cbiesinger Feb 14, 2023
8304968
Address comments
cbiesinger Feb 15, 2023
465c717
Add the JavaScript API
cbiesinger Feb 15, 2023
896e95d
void->undefined and add an Issue comment regarding Promise
cbiesinger Feb 15, 2023
07eb407
Slightly more direct way to get the origin
cbiesinger Feb 15, 2023
8948f99
Add a multi-IDP note and clarify a signin note
cbiesinger Feb 15, 2023
f19c445
Elaborate on state clearing
cbiesinger Feb 16, 2023
663f421
Merge remote-tracking branch 'upstream/main' into status2
cbiesinger Aug 11, 2023
090262d
Fix bikeshed syntax errors
cbiesinger Aug 11, 2023
d682586
Merge branch 'syntax' into status2
cbiesinger Aug 11, 2023
9557220
Merge remote-tracking branch 'upstream/main' into status2
cbiesinger Aug 11, 2023
0c154cb
define interaction with clear-site-data
cbiesinger Aug 11, 2023
d932e3f
better structure
cbiesinger Aug 11, 2023
f128898
less prescriptive about parameter location
cbiesinger Aug 11, 2023
71083c8
typo
cbiesinger Aug 11, 2023
3fbe365
period
cbiesinger Aug 11, 2023
238fdf4
fix merge error
cbiesinger Aug 11, 2023
13ca4f7
elaborate on cookie deletion
cbiesinger Aug 11, 2023
4db1336
Merge remote-tracking branch 'upstream/main' into status2
cbiesinger Aug 23, 2023
0c77ac9
review comments
cbiesinger Aug 23, 2023
afe7360
fix IDL syntax error
cbiesinger Aug 23, 2023
ddb3f24
automation
cbiesinger Aug 23, 2023
2098134
fix most comments from the PR
cbiesinger Sep 7, 2023
5b091a0
more editorial fixes
cbiesinger Sep 7, 2023
6a38c4b
add subheadings to signin status api section
cbiesinger Sep 7, 2023
654908f
specify IDP signin flow
cbiesinger Sep 8, 2023
652b436
Better specify popup creation
cbiesinger Sep 19, 2023
fb02431
Editorial comments from TallTed
cbiesinger Sep 20, 2023
d70fa1f
npm comments
cbiesinger Sep 20, 2023
620848c
update HTTP header section
cbiesinger Sep 20, 2023
b6b9be3
editorial fixes
cbiesinger Sep 20, 2023
436ee85
update IDL
cbiesinger Sep 20, 2023
3c8eb4a
fix typo
cbiesinger Sep 20, 2023
04e7156
better handle header origins
cbiesinger Sep 25, 2023
99147b3
clarify some traversable things
cbiesinger Sep 25, 2023
e7ab849
signin -> login
cbiesinger Sep 25, 2023
1fbab48
missed one
cbiesinger Sep 25, 2023
7f6eef5
npm comments
cbiesinger Sep 27, 2023
0f0c4fe
review comments and change signin to login
cbiesinger Sep 28, 2023
e80e54a
signin_url -> login_url
cbiesinger Sep 28, 2023
bf30c3d
replace a few more sign-ins
cbiesinger Sep 28, 2023
49fe2ad
linkify
cbiesinger Sep 28, 2023
2133a0b
review comments
cbiesinger Oct 3, 2023
d28201f
get a login status entry algorithm
cbiesinger Oct 3, 2023
0d55b05
review comments
cbiesinger Oct 10, 2023
60cdb08
review comments
cbiesinger Oct 12, 2023
48e4d1a
last? comments
cbiesinger Oct 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
275 changes: 267 additions & 8 deletions spec/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ spec: webdriver; urlPrefix: https://w3c.github.io/webdriver/
text: no such alert; url: dfn-no-such-alert
text: error code; url: dfn-error-code
text: validating capabilities; url: dfn-validate-capabilities
spec: webappsec-fetch-metadata; urlPrefix: https://w3c.github.io/webappsec-fetch-metadata/
type: dfn
text: Directly User-Initiated Requests; url: directly-user-initiated
</pre>

<pre class=link-defaults>
Expand All @@ -49,6 +52,7 @@ spec:html; type:dfn; for:environment settings object; text:global object
spec:html; type:dfn; for:html-origin-def; text:origin
spec:webidl; type:dfn; text:resolve
spec:webdriver2; type:dfn; text:error
spec:fetch; type:dfn; for:/; text:response
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be necessary... are you sure it's needed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I got a warning from bikeshed without it (it was ambiguous. Bikeshed actually picked the right one, but it seemed better not to rely on that)

</pre>

<style>
Expand Down Expand Up @@ -314,6 +318,130 @@ value (which is used when a resource loaded as a third-party, not first-party).
for an [=IDP=] to adopt the FedCM API. It doesn't introduce security issues on the API because the
[=RP=] cannot inspect the results from the fetches in any way.

<!-- ============================================================ -->
## The Login Status API ## {#browser-api-login-status}
<!-- ============================================================ -->

### Login Status Map ### {#hdr-login-status-map}

Each [=user agent=] keeps a global, persistent <dfn>Login Status
cbiesinger marked this conversation as resolved.
Show resolved Hide resolved
map</dfn>, an initially empty [=map=]. The [=map/keys=] in this map are
[=/origin=] (of [=IDPs=]), and the [=map/values=] are enums that can be one of
"<dfn><code>unknown</code></dfn>", "<dfn><code>logged-in</code></dfn>",
and "<dfn><code>logged-out</code></dfn>".

<div algorithm>
To <dfn>get the login status</dfn> for an [=/origin=] |origin|:
1. If [=Login Status map=][|origin|] exists, return it.
1. Otherwise, return [=unknown=].

</div>

<div algorithm>
To <dfn>set the login status</dfn> for an [=/origin=] |origin| to
value |value|:
1. Assert that |value| is one of [=logged-in=] or [=logged-out=].
1. [=map/Set=] [=Login Status map=][|origin|] to |value|.

</div>

### HTTP header API ### {#login-status-http}

[=IDPs=] can set the login status using an HTTP [=response=] [=header=] as follows.

Issue: The HTTP header checking should move into the Fetch spec, since it
affects all resource loads.

For each [=http-redirect fetch=] and [=http fetch=]'s [=response=], let |value|
be the result of [=get a structured field value=] from the response's header
list with name "<dfn><code>Set-Login</code></dfn>" and type "`item`". If |value| is not null,
process this header as follows:

<div algorithm="process the login status header">
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=].

</div>

### JavaScript API ### {#login-status-javascript}

[=IDPs=] can also use a JavaScript API to update the stored login status:
cbiesinger marked this conversation as resolved.
Show resolved Hide resolved


<pre class="idl">
enum LoginStatus {
"logged-in",
"logged-out",
};

[Exposed=Window, SecureContext]
interface NavigatorLogin {
Promise&lt;undefined&gt; setStatus(LoginStatus status);
samuelgoto marked this conversation as resolved.
Show resolved Hide resolved
};

partial interface Navigator {
[SecureContext] readonly attribute NavigatorLogin login;
};
</pre>

<div algorithm="setStatus">
When {{NavigatorLogin/setStatus()}} is called with argument |status|:
cbiesinger marked this conversation as resolved.
Show resolved Hide resolved
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|.

</div>

### 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 <a http-header>Clear-Site-Data</a> header with a
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if this is sent from a subresource or iframe that does not match the top-level? I was trying to find an answer in Clear-Site-Data and it seems the spec is not updated at all to account for any sort of partitioning, but maybe we can at least add an issue to make sure we handle that at some point...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm. I found w3c/webappsec-clear-site-data#72... updated this wording.

value of `"cookies"` or `"*"`, and the [=/request=]'s [=request/client=] is
not null, and the client's [=environment settings object/origin=] is [=same
origin=] with the [=top-level origin=]
:: while [$clear cookies for origin|clearing cookies for
origin$] it MUST remove any entries in the [=Login Status Map=] where
the [=map/key=] is the input origin.

Issue: Once Clear-Site-Data [supports partitioned cookies](https://github.com/w3c/webappsec-clear-site-data/issues/72),
this wording should be updated.

Note: Other website-initiated cookie changes should not affect this map. When
[=IDP=] login state changes, it should send an explicit [=Set-Login=] header.
[=RP=] state should not affect this map since it only reflects [=IDP=] state.

<!-- ============================================================ -->
## The connected accounts set ## {#browser-connected-accounts-set}
<!-- ============================================================ -->
Expand Down Expand Up @@ -559,21 +687,82 @@ To <dfn>create an IdentityCredential</dfn> given an {{IdentityProviderConfig}}
or a pair (failure, bool), where the bool indicates whether to skip delaying
the exception thrown.
1. Assert: These steps are running [=in parallel=].
1. Let |loginStatus| be the result of [=get the login status=] with
the [=/origin=] of |provider|'s {{IdentityProviderConfig/configURL}}.
1. If |loginStatus| is [=unknown=], a user agent MAY set it to [=logged-out=].
1. If |loginStatus| is [=logged-out=], the user agent MUST do one of the following:

* Return (failure, false).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this to allow UAs to reduce prompt spam?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

* Prompt the user whether to continue. If the user continues, the user
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this so that we support button flows? Or is this strictly necessarily for dealing with the timing attack? If this is only to support button flows, can't we handle this case in a separate PR?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it so that the following flow works reasonably, which I think is what Firefox wants to do:

  • UA prompts user to select an IDP before it does anything
  • user clicks the IDP
  • IDP is logged out
  • UA should probably should show something in response to that user clicks?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is inside the "create an IdentityCredential" algorithm: nothing happens before this, right? That is, "UA prompts user to select an IDP before it does anything" isn't captured before we get to this point, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean? The potential IDP selector is handled on (new) line 623, already existing in the spec. "create an IdentityCredential" is called by DiscoverFromExternalSource.

agent SHOULD set |loginStatus| to [=unknown=]. This MAY include an
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
agent SHOULD set |loginStatus| to [=unknown=]. This MAY include an
agent SHOULD set |loginStatus| to [=unknown=]. This MUST include an

Isn't this a MUST? Otherwise, how can we move forward with the algorithm if the loginStatus is 'logged-out'?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we also have to "wait" somewhere here until the user becomes 'logged-in'?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That happens if the user triggers the affordance to "show an IDP login dialog" and is encapsulated in that algorithm.

I don't think the SHOULD needs to be a MUST; the algorithm should work fine as-is, no? I left it that way because some user agents don't really want to use an unknown state.

affordance to [=show an IDP login dialog=].

* If the user cancels this dialog, return (failure, true).
* If the user triggers this affordance:
1. Let |config| be the result of running [=fetch the config file=]
with |provider| and |globalObject|.
1. If |config| is failure, return (failure, true).
1. [=Show an IDP login dialog=] with |config|.
1. If that algorithm returns failure, return (failure, true).

Issue: We should perhaps provide a way to let the [=RP=] request that
the second option is provided, possibly gated on a user gesture.
See [this issue](https://github.com/fedidcg/FedCM/issues/442) for discussion.
1. Let |requiresUserMediation| be |provider|'s {{IdentityProviderConfig/configURL}}'s [=/origin=]'s
[=requires user mediation=].
1. Let |mediation| be |options|'s {{CredentialRequestOptions/mediation}}.
1. If |requiresUserMediation| is true and |mediation| is
"{{CredentialMediationRequirement/silent}}", return failure.
1. Let |config| be the result of running [=fetch the config file=] with |provider| and
|globalObject|.
"{{CredentialMediationRequirement/silent}}", return (failure, true).
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. Let |accountsList| be the result of [=fetch the accounts list=] with |config|, |provider|,
and |globalObject|.
1. <dfn>Fetch accounts list step</dfn>: Let |accountsList| be the result of
[=fetch the accounts list=] 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=].
A user agent may decide to skip this step if no credentials were
sent to server.

Note: For example, if the fetch failed due to a DNS error, no
credentials were sent and therefore the [=IDP=] did not learn
the user's identity. In this situation, we do not know whether
the user is signed in or not and so we may not want to reset
cbiesinger marked this conversation as resolved.
Show resolved Hide resolved
the status.
1. <dfn>Mismatch dialog step</dfn>: If |loginStatus| is [=logged-in=], show a
dialog to the user. The contents of this dialog are defined by the user
agent. This dialog SHOULD provide an affordance for the user to trigger
the [=show an IDP login dialog=] algorithm with |config|; this dialog
is the <dfn>confirm IDP login dialog</dfn>.

Note: This situation happens when the browser expects the user
to be signed in, but the accounts fetch indicated that the user
is signed out.

Note: This dialog ensures that silent tracking of the user is
impossible by always showing UI of some kind when credentials
were sent to the server.

1. Wait until one of the following occurs:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be a substep of the mismatch dialog step? Or can it just be step 3 (the step after)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it needs to be a substep, because all of this only happens if loginStatus is logged-in.


* If the user closes the dialog, return (failure, true).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this return failure immediately?

This allows a user-visible read of the logged in bit.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand, since this requires the user to do something the timing is effectively random, indistinguishable from the delayed promise rejection?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rejecting in a user-specified time is different than rejecting after a fixed 120s. So by seeing a rejection before that point, the IDP can determine they were not "logged-in".

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, as of c8609ec the 120s has been replaced with a random timer.


* If the [=show an IDP login dialog=] algorithm was triggered:

1. Let |result| be the result of that algorithm.
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. Assert: |accountsList| is not failure and the size of |accountsList| is not 0.
1. [=Set the login status=] for the [=/origin=] of the
{{IdentityProviderConfig/configURL}} to [=logged-in=].
1. If |provider|'s {{IdentityProviderConfig/loginHint}} is not empty:
1. For every |account| in |accountList|, remove |account| from |accountList| if |account|'s
cbiesinger marked this conversation as resolved.
Show resolved Hide resolved
{{IdentityProviderAccount/login_hints}} does not [=list/contain=] |provider|'s
{{IdentityProviderConfig/loginHint}}.
1. If |accountsList| is failure, return (failure, false).
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=]
with |acc| and |globalObject|.
Expand All @@ -595,7 +784,7 @@ the exception thrown.
[=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
<dfn>auto-reauthenticated</dfn>.
1. Otherwise, if |mediation| is "{{CredentialMediationRequirement/silent}}", return failure.
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
Expand Down Expand Up @@ -732,6 +921,9 @@ or failure.
1. [=converted to an IDL value|Convert=] |json| to an {{IdentityProviderAPIConfig}} stored
in |config|.
1. If one of the previous two steps threw an exception, set |config| to failure.
1. Set |config|.{{IdentityProviderAPIConfig/login_url}} to the result of [=computing
the manifest URL=] with |provider|, |config| and |globalObject|.
1. If |config|.{{IdentityProviderAPIConfig/login_url}} is null, return failure.
1. Wait for both |config| and |configInWellKnown| to be set.
1. If |configInWellKnown| is true, return |config|. Otherwise, return failure.
</div>
Expand Down Expand Up @@ -765,6 +957,7 @@ dictionary IdentityProviderAPIConfig {
required USVString accounts_endpoint;
required USVString client_metadata_endpoint;
required USVString id_assertion_endpoint;
required USVString login_url;
IdentityProviderBranding branding;
};
</xmp>
Expand Down Expand Up @@ -1123,6 +1316,31 @@ and a |responseBody|, run the following steps. This returns an [=ordered map=].
1. Return |json|.
</div>

<div algorithm>
To <dfn>show an IDP login dialog</dfn> given an {{IdentityProviderAPIConfig}} |config|, run
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This algorithm doesn't work for redirect login flows, correct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should work for same-origin redirects since all that is required is that the close() call (and the status setting) is from the same origin. Is there a use case for cross-origin redirect flows?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant for instances where the login dialog is in the same navigatable, and then navigate the user back to this page. I think I remember that being out of scope here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not positive I understand you correctly but I think that's out of scope yeah

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this refers to flow that require cross origin navigation, for technical reasons or cases with authentication intermediaries which are currently not properly covered by this

the following steps. This returns success or failure.
1. [=Create a fresh top-level traversable=] with URL
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the URL is null?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a validation step to fetching the config file to ensure that signin_url is also valid here. I also think that this represents the desired semantics better (don't accept the config file if there is no login_url even if login_url is not triggered during this specific request)

|config|.{{IdentityProviderAPIConfig/login_url}}.
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. Let |loginStatus| be the result of [=get the login status=]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this is a bit weird in the implementation. Because we do not know whether we process the header before the idp.close, we allow header processing to also work. But I guess the spec is sync enough that it's not possible...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the spec is conceptually better than the impl; maybe we can do things better in our impl...

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
flow. It is also possible that this change happened in
a different browsing context.
1. If |loginStatus| is [=logged-in=], return success.
1. Otherwise, return failure.
samuelgoto marked this conversation as resolved.
Show resolved Hide resolved
</div>

<!-- ============================================================ -->
## The IdentityProvider Interface ## {#browser-api-identity-provider-interface}
<!-- ============================================================ -->
Expand All @@ -1139,13 +1357,23 @@ This specification introduces the {{IdentityUserInfo}} dictionary as well as the
};

[Exposed=Window, SecureContext] interface IdentityProvider {
static undefined close();
static Promise&lt;sequence&lt;IdentityUserInfo&gt;&gt; getUserInfo(IdentityProviderConfig config);
};
</pre>

Issue: [Decide](https://github.com/fedidcg/FedCM/issues/476) whether {{IdentityProvider}} is the
correct location for the {{IdentityProvider/getUserInfo()}} method.

A {{IdentityProvider/close}} function is provided to signal to the browser that
the login flow is finished. The reason for this function in addition to the
header is that even when the user is already logged in, the login flow may not
be finished yet; for example, an [=IDP=] may want to prompt the user to verify
their phone number. To allow for such flows, the [=IDP=] must call
{{IdentityProvider/close}} when the flow is fully done.

See the [=show an IDP login dialog=] algorithm for more details.

An {{IdentityUserInfo}} represents user account information from a user. This information is exposed
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=]
Expand Down Expand Up @@ -1754,6 +1982,36 @@ The [=remote end steps=] are:

1. Return [=success=] with data `null`.

## Confirm IDP login ## {#webdriver-confirmidplogin}

<figure id="table-webdriver-confirmidplogin" class="table">
<table class="data">
<thead>
<tr>
<th>HTTP Method</th>
<th>URI Template</th>
</tr>
</thead>
<tbody>
<tr>
<td>POST</td>
<td>`/session/{session id}/fedcm/confirmidplogin`</td>
</tr>
</tbody>
</table>
</figure>

The [=remote end steps=] are:

1. If no FedCM dialog is currently open, or the dialog is not a [=confirm IDP
login dialog=] return a [=error|WebDriver error=] with [=error code=]
[=no such alert=].

1. Act as if the user had clicked the "continue" button in the dialog and
initiate the login flow.

1. Return [=success=] with data `null`.

## Account list ## {#webdriver-accountlist}

<figure id="table-webdriver-accountlist" class="table">
Expand Down Expand Up @@ -1865,7 +2123,8 @@ The [=remote end steps=] are:
[=error code=] [=no such alert=].

1. Let |type| be a string that is "`AutoReauthn`" if the user is being [=auto-reauthenticated=],
or "`AccountChooser`" otherwise.
or "`AccountChooser`" is the dialog is an account chooser, or "`ConfirmIdpLogin`" if the
dialog is a [=confirm IDP login dialog=].

1. Return [=success=] with data |type|.

Expand Down
Loading