-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update IDP signin status API explainer (#505)
* Update IDP signin status API explainer Per discussion at TPAC. * restrict to secure context * s/signed/logged/g * remove action * ted comments * better describe parsing of the header * review comments
- Loading branch information
1 parent
0063ee6
commit ab23aff
Showing
1 changed file
with
42 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,7 +26,7 @@ this API to let identity providers (IDPs) tell the browser when the user signs | |
in to and out of the IDP. The IDP Sign-in Status API does not grant the | ||
identity provider any permissions. Using the IDP sign-in status API is not a | ||
way for a site to prove that it is an identity provider. The purpose of the | ||
Idp-Signin-Status API is to enable identity providers to disable the FedCM API | ||
IDP Sign-in Status API is to enable identity providers to disable the FedCM API | ||
for their IDP in order to deliver a better user experience. | ||
|
||
In addition, with the browser gaining knowledge about IDPs, this may allow | ||
|
@@ -36,39 +36,50 @@ settings page allowing the user to disable certain IDPs for use with FedCM. | |
|
||
## Proposed API | ||
|
||
The "Headers" and "JS API" sections describe the proposed | ||
[Login Status API](https://github.com/fedidcg/login-status). We describe them | ||
in this document as well for easier readability. | ||
|
||
### Headers | ||
|
||
``` | ||
SignIn-Status: action=signin; type=idp | ||
SignIn-Status: action=signout-all; type=idp | ||
```http | ||
Set-Login: logged-in | ||
Set-Login: logged-out | ||
``` | ||
|
||
These headers can be sent on the toplevel load as well as subresources such as | ||
XMLHttpRequest (this is necessary for at least one IDP). | ||
|
||
The signout-all header should only be sent when no accounts remain signed in | ||
to the IDP, i.e. when this action has signed out all accounts or if this | ||
was the last/only account getting signed out. | ||
The signout header should only be sent when no accounts remain logged in | ||
to the IDP, i.e., when this action has logged out all accounts or if this | ||
was the last/only account getting logged out. | ||
|
||
This will be parsed as a [structured field](https://fetch.spec.whatwg.org/#concept-header-list-get-structured-header) | ||
with type `item`. For now, we only use bare item part, but this lets us extend | ||
the header to support parameters in the future. | ||
|
||
### JS API | ||
|
||
```idl | ||
dictionary SigninStatusOptions { | ||
boolean idp = false; | ||
enum LoginStatus { | ||
"logged-in", | ||
"logged-out", | ||
}; | ||
interface NavigatorLogin { | ||
Promise<void> setStatus(LoginStatus status); | ||
}; | ||
partial interface Navigator { | ||
Promise<void> recordSignedIn(optional SigninStatusOptions options); | ||
Promise<void> recordSignedOut(optional SigninStatusOptions options); | ||
[SecureContext] readonly NavigatorLogin login; | ||
}; | ||
``` | ||
|
||
Alternatively, an IdP can call the IdP Sign-in Status API via JS calls through | ||
the static functions `navigator.recordSignedIn({idp: true})` and | ||
`navigator.recordSignedOut({idp: true})`. These are to be called from the IDP's | ||
origin, and mark the current origin as signed in or signed out. | ||
the static functions `navigator.login.setStatus("logged-in")` and | ||
`navigator.login.setStatus("logged-out")`. These are to be called from the IDP's | ||
origin, and mark the current origin as logged-in or logged-out. | ||
|
||
```idl | ||
[Exposed=Window] | ||
|
@@ -101,16 +112,16 @@ See further below for a description of the semantics. | |
### Semantics | ||
|
||
For each IDP (identified by its config URL) the browser keeps a tri-state | ||
variable representing the sign-in state with possible values “signed-in”, | ||
“signed-out”, and “unknown”, defaulting to “unknown”. | ||
variable representing the sign-in state with possible values “logged-in”, | ||
“logged-out”, and “unknown”, defaulting to “unknown”. | ||
|
||
When receiving the sign-in header, the state will be set to “signed in”. In | ||
When receiving the sign-in header, the state will be set to “logged in”. In | ||
case of subresources, to limit abuse, the header is only processed if the | ||
resource is same-origin with the document. | ||
|
||
Similar for the sign-out header. | ||
|
||
In some cases, a user can get signed out server-side while the user is not on | ||
In some cases, a user can get logged out server-side while the user is not on | ||
the IDP website. For example, the IDP may require re-authentication every N | ||
days, or the user may have changed their password (or deleted their account) on | ||
a different browser, forcing re-login. This proposal does not have special | ||
|
@@ -123,24 +134,24 @@ There is [some discussion](https://crbug.com/1381505) on whether the sign-in hea | |
|
||
When an RP calls navigator.credentials.get(): | ||
|
||
* If the sign-in state on the provided config URL is “signed out”, no | ||
* If the sign-in state on the provided config URL is “logged out”, no | ||
network requests will be made and the promise is rejected (with a delay | ||
as usual (step 3 of | ||
[the algorithm](https://fedidcg.github.io/FedCM/#dom-identitycredential-discoverfromexternalsource-slot))) | ||
* Otherwise, network requests are made as usual | ||
|
||
When the accounts endpoint response is successful and has at least one account: | ||
|
||
* The sign-in state is set to “signed-in” if it was previously “unknown” | ||
* The sign-in state is set to “logged-in” if it was previously “unknown” | ||
|
||
|
||
When an error is received from the accounts endpoint or no accounts are returned: | ||
|
||
* If the sign-in state was unknown, the sign-in state is set to “signed out”. No UI is displayed and the promise is rejected as usual | ||
* This is used when launching this API, when the browser has no stored IDP sign-in data, and also when an IDP starts supporting FedCM, where the user can also be signed in without the sign-in status being set. This allows us to handle these cases without being required to show UI when the user is not signed in | ||
* If the sign-in state was unknown, the sign-in state is set to “logged out”. No UI is displayed and the promise is rejected as usual | ||
* This is used when launching this API, when the browser has no stored IDP sign-in data, and also when an IDP starts supporting FedCM, where the user can also be logged in without the login status being set. This allows us to handle these cases without being required to show UI when the user is not logged in | ||
* This does incur a one-time timing attack per IDP. Since this can only happen once per IDP/browser profile, it seems impractical for an attacker to rely on. | ||
* An alternative solution is to show the sign-in UI even in this case | ||
* If the sign-in state was “signed in”, the sign-in state is set to “signed out”. An error dialog is displayed that also allows the user to sign in to the IDP. The exact UI is TBD; the dialog may not explicitly say something like “we thought you were logged in to the IDP”. | ||
* If the sign-in state was “logged in”, the sign-in state is set to “logged out”. An error dialog is displayed that also allows the user to sign in to the IDP. The exact UI is TBD; the dialog may not explicitly say something like “we thought you were logged in to the IDP”. | ||
* The primary case where this will happen is if the session is invalidated server-side, either because of session-length settings, because the user forced logout on other devices, or other reasons. | ||
* We show a dialog in this situation to discourage trackers using this | ||
* This dialog is why there is a sign-in URL being added in this proposal, so that the user has a way to recover instead of being presented with a useless dialog. However, having this URL is also useful for other UI enhancements. | ||
|
@@ -154,38 +165,26 @@ See [https://github.com/fedidcg/FedCM/blob/main/meetings/2022/FedCM_%20Options%2 | |
|
||
### Header syntax | ||
|
||
We chose action=signout-all to make it clear that this header should only be | ||
sent when all accounts from this IDP are signed out. | ||
|
||
We could instead or in addition have allowed notifying the user agent of | ||
individual accounts being signed in/out, such as: | ||
individual accounts being logged in/out, such as: | ||
|
||
``` | ||
SignIn-Status: action=signin; count=2; type=idp | ||
SignIn-Status: action=signout; new-count=1; type=idp | ||
Set-Login: logged-in; count=2; type=idp | ||
Set-Login: logged-out; new-count=1; type=idp | ||
``` | ||
|
||
Or | ||
|
||
``` | ||
SignIn-Status: action=signin; [email protected]; type=idp | ||
SignIn-Status: action=signout; [email protected]; type=idp | ||
Set-Login: logged-in; [email protected]; type=idp | ||
Set-Login: logged-out; [email protected]; type=idp | ||
``` | ||
|
||
However, we decided to go with the simpler syntax because we do not currently | ||
have a use case that requires the extra information. | ||
|
||
Additionally, the second option would require the browser to track which | ||
specific account IDs are signed in, so that it can tell when there no | ||
more signed in accounts for this IDP. This introduces extra complexity, | ||
whereas the IDP already knows how many accounts are signed in and thus | ||
specific account IDs are logged in, so that it can tell when there no | ||
more logged in accounts for this IDP. This introduces extra complexity, | ||
whereas the IDP already knows how many accounts are logged in and thus | ||
whether no accounts remain after this signout action. | ||
|
||
### The Login Status API | ||
|
||
We are also considering with Safari and Firefox how this API relates to the Login Status API [here](https://github.com/privacycg/is-logged-in/issues/53). | ||
|
||
In this proposal, we are using generic header and JS function names so that the same API and | ||
headers can be used for is-logged-in while also recording the optional type (i.e. is this | ||
an IDP or not). | ||
|