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

Allow IdPs to continue and finish the request in a popup window #1

Open
cbiesinger opened this issue Apr 11, 2024 · 20 comments
Open

Allow IdPs to continue and finish the request in a popup window #1

cbiesinger opened this issue Apr 11, 2024 · 20 comments

Comments

@cbiesinger
Copy link

cbiesinger commented Apr 11, 2024

(this has been split out of w3c-fedid/FedCM#477 )

FedCM’s account chooser and disclosure dialog only allows asking for permission to share standard claims (e.g. user’s name, email address and profile picture). However, commonly Identity Providers (IdPs) need to ask for additional information before returning the token to the relying party (RP), such as requesting re-authentication, scopes beyond standard claims (e.g. API access), verifying up-to-date contact information, parental controls, etc.

There is currently no mechanism that an IdP can use to use their own words to request their user's permission before returning a token to the RP.

@cbiesinger
Copy link
Author

cbiesinger commented Apr 11, 2024

Proposal

We are proposing to extend the ID assertion response to let the IDP specify a field called continue_on (which can be used in replacement of token). This field would contain a (same-origin) URL that the user agent can use to show a popup so that the user can continue the signin flow.

Once finished, the identity provider will call a new function IdentityProvider.resolve(token) in the popup to indicate that the flow is finished and to provide the token to pass back to the RP.

IDL

dictionary IdentityResolveOptions {
 USVString accountId;
};

partial interface IdentityProvider
    // Allows an IdP to return a token to the RP from the content area,
    // as opposed to over HTTP with the id_assertion_endpoint.
    static Promise<undefined> resolve(USVString token,
        optional IdentityResolveOptions options = {});
};

And the dictionary for the ID assertion response would be extended like this:

dictionary IdentityProviderToken {
  optional USVString token;
  optional USVString continue_on;
};

Example

{
  // In the id_assertion_endpoint, instead of returning a typical
  // "token" response, the IdP decides that it needs the user to
  // continue on pop-up window:
  "continue_on": "/oauth/authorize?scope=..."
}

The popup might then contain code like this:

document.getElementById("allow_btn").addEventListener("click", async () => {
  let accessToken = await fetch(`/generate_access_token.cgi`);
  // Closes the window and resolves the promise (that is still hanging
  // in the relying party's renderer) with the value that is passed.
  IdentityProvider.resolve(accessToken);
});

The user agent will then close the popup and resolve the promise (returned from navigator.credentials.get) with the provided token.

If for some reason the user has changed in the popup (e.g. the IDP offers a “switch user” function or in delegation cases), the resolve call takes an optional second argument allowing something like:

  IdentityProvider.resolve(token, {accountId: "1234");

If not provided, the user agent will assume the account ID is unchanged from what the user has selected.

Considerations

Because this happens after the user has selected an account, it is safe to allow access to unpartitioned cookies in the popup. However, we still do not allow direct communication with the RP – the popup behaves as if noopener,noreferrer was specified (thus, window.opener is null). The only way to communicate with the RP should be a one-time IdentityProvider.resolve call, which also closes the popup.

We only want to allow popups when we had a user interaction. Therefore, we allow them when the user selected an account in the account chooser, or in button mode (which always requires user activation). But we don’t want to allow the popup for mediation: silent (a popup is pretty loud), and for mediation: optional for the widget mode we check for transient user activation. Otherwise, we open no popup and reject the promise.

Due to its versatility, this proposal can also be used for cases where no token will be returned, such as for showing custom error messages. We think this is a feature, not a bug.

@achimschloss
Copy link

Some thoughts:

  • Are there restrictions on re-directs within the pop-up? In the current prototype there aren't, but resolve / close can only be called from the IDP domain - As discussed re-directs are essential for IDPs and must be possible
  • Are there requirements for user interaction in the popup? There should not be given the IDP might not need a user interaction to continue, and the browser UX already had a user interaction

@cbiesinger
Copy link
Author

This is intended to be a regular popup where you can redirect as much as you like. Can you remind me whether you needed the resolve call to be possible from a different domain as well? (close is largely unrelated to this proposal)

No requirements for user interaction, as you point out.

@samuelgoto
Copy link
Collaborator

Posting this on behalf of @panva

It would be cool if the IdP had a HTTP header version of the IdentityProvider.resolve() call to fit within the current deployment.

@samuelgoto
Copy link
Collaborator

Also from @panva:

Do the requests shown in a window in response to the "IDP login dialog" flow include the "Sec-Fetch-Dest: webidentity" HTTP header? If not, why?

@samuelgoto
Copy link
Collaborator

It would be cool if the IdP had a HTTP header version of the IdentityProvider.resolve() call to fit within the current deployment.

That seems reasonable to me. @cbiesinger, any concern?

@samuelgoto
Copy link
Collaborator

Do the requests shown in a window in response to the "IDP login dialog" flow include the "Sec-Fetch-Dest: webidentity" HTTP header? If not, why?

I believe the answer is "no". @cbiesinger ack?

@vaceksimon
Copy link

+1 to the HTTP header version of the js call. This could also be considered for the dynamic sign-in flow. After authenticating the user, the IdP could send the successful authn response only with extra headers causing the pop-up window to close, without the need to modify the signing in process any futher.

@panva
Copy link

panva commented Apr 26, 2024

It would be cool if the IdP had a HTTP header version of the IdentityProvider.resolve() call to fit within the current deployment.

That seems reasonable to me. @cbiesinger, any concern?

For clarity I don't think it would be cool per se. I think it is a prerequisite for being able to fit the FedCM signals to an existing IdP login interaction rather than having to define a new login form response that is a blank HTML with a <script> block.

@cbiesinger
Copy link
Author

Also from @panva:

Do the requests shown in a window in response to the "IDP login dialog" flow include the "Sec-Fetch-Dest: webidentity" HTTP header? If not, why?

They do not. Similar to the IDP login flow, the continuation URL gets shown in a regular browser popup so the destination is not semantically "the FedCM flow", hence we use the regular destination. (if we wanted to use webidentity, that would also prompt the question what we should send for subresources)

@cbiesinger
Copy link
Author

It would be cool if the IdP had a HTTP header version of the IdentityProvider.resolve() call to fit within the current deployment.

That seems reasonable to me. @cbiesinger, any concern?

For clarity I don't think it would be cool per se. I think it is a prerequisite for being able to fit the FedCM signals to an existing IdP login interaction rather than having to define a new login form response that is a blank HTML with a <script> block.

Makes sense to me, we could definitely define an HTTP header for this, similar to how we have an HTTP version of the login status API.

@panva
Copy link

panva commented Apr 26, 2024

FWIW the comments @samuelgoto re-posted from our private conversation don't parcularly pertain to continuation flow but rather any window popped up by FedCM.

@cbiesinger
Copy link
Author

@panva so you are suggesting that you would also like an HTTP version of IdentityProvider.close?

@panva
Copy link

panva commented Apr 26, 2024

@panva so you are suggesting that you would also like an HTTP version of IdentityProvider.close?

Yes, that's the one my message to @samuelgoto wss actually about.

@panva
Copy link

panva commented Apr 26, 2024

Anything I can't do with headers as an IdP is an annoyance because it means i need to add intermediary script only pages in my existing flow.

@samuelgoto samuelgoto changed the title Continuing the sign-in flow in a popup Allow IdP's to continue / finish the request in a popup window May 9, 2024
@samuelgoto samuelgoto changed the title Allow IdP's to continue / finish the request in a popup window Allow IdPs to continue / finish the request in a popup window May 9, 2024
@samuelgoto samuelgoto changed the title Allow IdPs to continue / finish the request in a popup window Allow IdPs to continue and finish the request in a popup window May 9, 2024
@ThisIsMissEm
Copy link

My only real problem with this, and why I think w3c-fedid/FedCM#590 is better is because this forces popups to be used, rather than just allowing the developer to choose what to do, e.g., full-page redirect or popup.

@cbiesinger
Copy link
Author

The problem with redirects is that it does not match super well to a JavaScript API, because by definition it can't return anything to the JavaScript because the document is gone.

@aaronpk
Copy link

aaronpk commented Jun 21, 2024

Is there a way we can define a version that uses HTTP headers instead of JavaScript?

@cbiesinger
Copy link
Author

As a replacement for IdentityProvider.resolve? Yes, that was also requested elsewhere, we can definitely do that

@wseltzer
Copy link
Contributor

Discussed at TPAC 2024 https://github.com/fedidcg/meetings/blob/main/2024/2024-09-24-TPAC-notes.md#continuation-api

Proposal advanced to Stage 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants