privacycg / is-logged-in

The IsLoggedIn API
93 stars 10 forks source link

Support for federated logins, or the ability to transfer IsLoggedIn #35

Open melanierichards opened 3 years ago

melanierichards commented 3 years ago

Porting to this repo; @johnwilander wrote:

Back in the original explainer, we explored an idea on how to support federated logins (logging in to one website with an account from another website that is not part of the same organization, as opposed to single sign-on which is about the same organization). This is what was said there:

Some websites allow the user to use an existing account with a federated login provider to bootstrap a new local user account and subsequently log in. The IsLoggedIn API needs to support such logins.

First, the federated login provider needs to call the API on its side, possibly after the user has clicked a “Log in with X” button:

navigator.initiateLoggedInFederated(destination: secure origin) –> Promise<void>

For the promise to resolve, the user needs to already have the IsLoggedIn status set for the federated login provider, i.e. the user needs to be logged in to the provider first.

Then the destination website has to call the API on its side:

   navigator.setLoggedInFederated(
      loginProvider: secure origin,
      username,
      credentialTokenType,
      optionalParams { }
   ) –> Promise<void>

The promise would only resolve if the loginProvider had recently called setLoggedInFederated() for this destination website.

What this comes down to is the capability to set IsLoggedIn on DependingSite by taking the user through specific steps on IdentityProviderSite. This would allow IdentityProviderSite to "transfer the ability to set IsLoggedIn" to DependingSite without there having to be e.g. a login form on SiteA.

We should discuss this opportunity without being tied to the original proposal quoted above. The important part is to explore how to support such a transfer capability.

achimschloss commented 3 years ago

https://github.com/privacycg/storage-access/issues/65

gffletch commented 3 years ago

Today Identity Federation usually happens in one of two use cases: (stating the obvious; question at the end:)

  1. The user is already logged in at the Federated Identity Provider and so the user doesn't have to login again This can have a couple sub use cases a. The user has done this before and so all consent issues have been resolved -- Generally in this case there is no UI shown to the user and the IDP just redirects back to the relying party with a "success state" (SAML: Assertion, OIDC: code+state) b. This is the first time the user is logging into this relying party -- Generally in this case the user is presented with some consent screen before the flow continues
  2. The user is NOT already logged in at the Federated Identity Provider -- In this case the user will first need to login to the Federated Identity Provider and potentially give consent before the flow completes

So the question is, how does the Federated Identity Provider convey to the browser that the user has successfully logged in and agreed to share their identity with the relying party? Should the browser inspect the direct or (form post redirect) for success components of the given protocol? (this seems brittle). Should the IDP return an HTTP Response Header with some data (given that in some flows no UI is shown to the user so no JS calls can be made)? Other thoughts?

We need to be able to handle the above use cases in the federated identity space.

michael-oneill commented 3 years ago

The specific informed consent of the user must have been obtained and recorded at the top-level site (relying party), otherwise the FIP cannot be rendered, or at least by default not use any browser storage (because ePrivacy). If prior consent has to be obtained before logging in, then maybe there is not a lot of point in a isLoggedIn API? In my view the issue is how can a browser determine that valid consent has been given, which primarily is about trusting the consent indication from the site, rather than the FIP subresource. If the browser cannot trust the indication then it must facilitate the consent process itself.

gffletch commented 3 years ago

@michael-oneill I'm not sure follow... take the following common case in enterprise (but also true in consumer space as well). Acme uses IDPService as it's enterprise IDP. When the user goes to mail.acme.com their browser is immediately redirected to acme.idpservice.example so the user can authenticate. Today there is not explicit consent from the user that they want to login via acme.idpservice.example because that is the only IDP supported. The user gives consent at acme.idpservice.example by virtue of logging in and knowing they will be sent back to acme.example to access their corporate services. I don't think we want to be introducing user friction in this flow.

Did you understand your points correctly?

michael-oneill commented 3 years ago

I thought I understood when I posted it, but I agree it is less than clear!

I was conflating the technical issue of how to get the browser to recognise the user was logged in (using the FIP but on another site), with the meta point about isLoggedIn being a proxy for user consent. Now I see ePrivacy is probably a red-herring because the existing law allows an exemption for logging-in (as long as the state information recorded was "strictly necessary to fulfil a purpose requested by the user").

Your use-case requires a way to communicate to the browser that the user had logged in (on another top level site using the FIP). I think that the setLoggedInFederated API can register register a "this user is logged-in" but my understanding is that this happens only if the user had logged in when the FIP was the top-level site.

If it could be used by a nested context (registering the logged-in state for the FIP origin) then that would work, but how does the browser know this is a valid use of the API? It has some clarity when the user has explicitly visited the FIP site (though this can be obscured), but not when called by an arbitrary embedded subresource.

This gets back to my initial point about user consent, in that there is has to be a way for the browser to recognise that consent has been validly given, and that maybe the only way to do that is if the browser facilitated the consent process itself, i.e. by presenting the information in its own UI and prompting the user.

gffletch commented 3 years ago

The browser managing the consent is a bit what safari does on iOS today when an app sends the user to a browser to login (OIDC/OAuth2).

I still feel like a simple solution here would be for the relying party to declare what identity providers it supports via a .well-known meta-data file that the browser can read. When the relying part redirects to one of these declared identity providers, the browser could intercept the redirect and ask for explicit consent (first time only or a way to allow the user to remember the decision) before completing the redirect. From that point on, the browser could allow the existing redirect flows between those specific domains to complete. Since the user has given explicit consent, when the IDP setIsLoggedIn() it can be trusted. This gets the browser out of trying to guess if the user has given consent (by looking at browser mediated authentication methods) and instead collecting it explicitly. This should also stop any "ad bounce tracking" attempts to co-opt login protocols.

michael-oneill commented 3 years ago

That would work, but why do you need the redirect? If the browser is managing the consent prompt there is no need to access the FIP as a top-level page, the FIP could just be an embed.

gffletch commented 3 years ago

Mostly because that is the way both SAML and OpenID Connect work. That's not to say we couldn't manage the redirect in an iframe (I'm assuming that's what you meant by an "embed"). But both of those protocols leverage cookies to protect against CSRF attacks and cookies in iframes have problems these days.

I'm looking for solutions that won't break the identity flows for most of the web :)

michael-oneill commented 3 years ago

Cookies are restricted in iframes for the same privacy reason, they may be restricted in top frames in future, hence the isLoggedIn proposal. If the browser is involved in the consent acquisition process then these restrictions could be lifted, including in iframes.

gffletch commented 3 years ago

That would be great! There are a number of standard identity flows that use hidden iframes to refresh tokens/credentials. There are other potential issues with using iframes (aka click-jacking) but those may be able to be mitigated via other means.