Bug 209586 - recent ITP changes causes breakage for seamlessaccess.org
Summary: recent ITP changes causes breakage for seamlessaccess.org
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: Safari 13
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: John Wilander
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-03-26 01:07 PDT by Leif Johansson
Modified: 2020-04-01 08:30 PDT (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Leif Johansson 2020-03-26 01:07:00 PDT
Hi,

The seamlessaccess.org project aims to improve the login user experience in the case when the user needs to select among a large number of IdPs (aka the NASCAR problem) without revealing any personal information to the site before the user has decided to proceed through an authentication flow via an external IdP. 

Our approach to the UX is to only force the user to identify (typically through search at seamlessaccess.org) their most commonly used IdP once and remember that and provide a way for sites to initiate a login flow to that IdP without learning the IdP until after the authentication response comes back to the site. 

Our current implementation (which we believe suffer breakage as a result of recent ITP changes) stores the users choice of IdP in localStorage at seamlessaccess.org and we provide a component for inclusion on sites which makes it possible for users to initiate a login flow. This is an approach similar to google accountchooser but unrelated to that implementation. An important difference is that we do not store any personal information (aka account) data but only the public URL of the IdP.

The part that seems to break under recent ITP changes is that we provide a login button as an iframe component (our implementation uses zoid) which displays the login choice to the user but without exposing the information to the top page; the component iframe wraps an inner iframe with which it communicates using postMessage calls to retrieve the IdP choice. The top page is not providing an API into the data displayed in the iframe and only after the user has clicked the button does the login flow eventually reach the site.

- We are aware that our service *could* track users if we wanted to. We rely on community audit and oversight to ensure that we behave responsibly.
- We understand that our pattern may be indistinguishable from sites that engage in predatory tracking behaviour
- We understand that we may need to find other ways to implement our pattern.
- We believe that switching to the recommended oauth2 flow would actually increase the amount of trackable state available about users in the whole system. Currently the service has no information about who the user is other than which IdP they have chosen to use.

We do not see what mechanism is available to us now or in the near future for the webkit platform to achieve our goals while maintaining user privacy.

Please advise.
Comment 1 Leif Johansson 2020-03-26 01:13:31 PDT
Let me add an apology for probably misusing bugzilla - I am new to this particular platform and I am sure I didn't enter the metadata properly.
Comment 2 John Wilander 2020-03-26 08:40:11 PDT
Hi, and thanks for filing, Leif!

(In reply to Leif Johansson from comment #0)
> Hi,
> 
> The seamlessaccess.org project aims to improve the login user experience in
> the case when the user needs to select among a large number of IdPs (aka the
> NASCAR problem) without revealing any personal information to the site
> before the user has decided to proceed through an authentication flow via an
> external IdP. 
> 
> Our approach to the UX is to only force the user to identify (typically
> through search at seamlessaccess.org) their most commonly used IdP once and
> remember that and provide a way for sites to initiate a login flow to that
> IdP without learning the IdP until after the authentication response comes
> back to the site. 
> 
> Our current implementation (which we believe suffer breakage as a result of
> recent ITP changes) stores the users choice of IdP in localStorage at
> seamlessaccess.org

Does this mean the user goes to seamlessaccess.org as first-party website and log in there? Do users then revisit seamlessaccess.org or is the login kind of a one-time thing?

> and we provide a component for inclusion on sites which
> makes it possible for users to initiate a login flow.

How does this component work? Is it an iframe from seamlessaccess.org or some other subresource from seamlessaccess.org?

How does the login flow work? Does it take the user to seamlessaccess.org for confirmation and then back to the relying party with some token? Or does the login flow happen in an embedded fashion on the relying party's website?


> This is an approach
> similar to google accountchooser but unrelated to that implementation. An
> important difference is that we do not store any personal information (aka
> account) data but only the public URL of the IdP.
> 
> The part that seems to break under recent ITP changes is that we provide a
> login button as an iframe component (our implementation uses zoid) which
> displays the login choice to the user but without exposing the information
> to the top page; the component iframe wraps an inner iframe with which it
> communicates using postMessage calls to retrieve the IdP choice.

From and to where does this postMessage communication go? I mean origins, such as seamlessaccess.org.

> The top
> page is not providing an API into the data displayed in the iframe and only
> after the user has clicked the button does the login flow eventually reach
> the site.
> 
> - We are aware that our service *could* track users if we wanted to. We rely
> on community audit and oversight to ensure that we behave responsibly.
> - We understand that our pattern may be indistinguishable from sites that
> engage in predatory tracking behaviour

Thanks for acknowledging these things. It's so much harder to reason about issues and solutions when there's a disconnect on these fundamentals.

> - We understand that we may need to find other ways to implement our pattern.
> - We believe that switching to the recommended oauth2 flow would actually
> increase the amount of trackable state available about users in the whole
> system. Currently the service has no information about who the user is other
> than which IdP they have chosen to use.

I would need more information to understand this. May using some concrete example will get me there?

> We do not see what mechanism is available to us now or in the near future
> for the webkit platform to achieve our goals while maintaining user privacy.
> 
> Please advise.
Comment 3 Leif Johansson 2020-03-26 11:47:30 PDT
(In reply to John Wilander from comment #2)
> Hi, and thanks for filing, Leif!
> 

Hi and thanks for reviewing!

> (In reply to Leif Johansson from comment #0)
> > Hi,
> > 
> > The seamlessaccess.org project aims to improve the login user experience in
> > the case when the user needs to select among a large number of IdPs (aka the
> > NASCAR problem) without revealing any personal information to the site
> > before the user has decided to proceed through an authentication flow via an
> > external IdP. 
> > 
> > Our approach to the UX is to only force the user to identify (typically
> > through search at seamlessaccess.org) their most commonly used IdP once and
> > remember that and provide a way for sites to initiate a login flow to that
> > IdP without learning the IdP until after the authentication response comes
> > back to the site. 
> > 
> > Our current implementation (which we believe suffer breakage as a result of
> > recent ITP changes) stores the users choice of IdP in localStorage at
> > seamlessaccess.org
> 
> Does this mean the user goes to seamlessaccess.org as first-party website
> and log in there? Do users then revisit seamlessaccess.org or is the login
> kind of a one-time thing?
> 

The user is redirected from the site to service.seamlessaccess.org (a SAML identity provider discovery request to be precise) and does a search for their IdP and selects it. The user is redirected back to the site with the URL of the IdP and the site then issues an authentication request to the IdP (SAML in our case but openidc would look the same since we don't do email-style webfinger discovery for privacy reasons). When the user picks the IdP the URL is stored in localStorage on service.seamlessaccess.org.

Note that what happens at service.seamlessacces.org isn't actually a login but a selection of an IdP. In some metaphysical sense I guess you could say that the user "logs on" to service.seamlessaccess.org by doing the IdP selection but this doesn't create any user-specific state anywhere.

> > and we provide a component for inclusion on sites which
> > makes it possible for users to initiate a login flow.
> 
> How does this component work? Is it an iframe from seamlessaccess.org or
> some other subresource from seamlessaccess.org?

it is an iframe from service.seamlessaccess.org/cta which in turn pulls in an iframe from service.seamlessaccess.org/ps which acually accesses the localStorage.

The idea is that users who almost never switch IdPs should have to go through the IdP selection dialog every day to login.

I am aware that some (I heard this from John Bradley) have suggested using a variation of payment providers to represent IdP selections in the browser. This comes pretty close to what we're trying to achive here except that our "payment providers" don't come with any personal information - its just a generic URL for the IdP.

> 
> How does the login flow work? Does it take the user to seamlessaccess.org
> for confirmation and then back to the relying party with some token? Or does
> the login flow happen in an embedded fashion on the relying party's website?

The actual login flow happens between the relying partys website and the users chosen IdP. No user token is passed back to the RP website - just the IdPs URL that comes back to the RPs website.
Comment 4 John Wilander 2020-03-26 15:06:29 PDT
(In reply to Leif Johansson from comment #3)
> (In reply to John Wilander from comment #2)
> > Hi, and thanks for filing, Leif!
> > 
> 
> Hi and thanks for reviewing!
> 
> > (In reply to Leif Johansson from comment #0)
> > > Hi,
> > > 
> > > The seamlessaccess.org project aims to improve the login user experience in
> > > the case when the user needs to select among a large number of IdPs (aka the
> > > NASCAR problem) without revealing any personal information to the site
> > > before the user has decided to proceed through an authentication flow via an
> > > external IdP. 
> > > 
> > > Our approach to the UX is to only force the user to identify (typically
> > > through search at seamlessaccess.org) their most commonly used IdP once and
> > > remember that and provide a way for sites to initiate a login flow to that
> > > IdP without learning the IdP until after the authentication response comes
> > > back to the site. 
> > > 
> > > Our current implementation (which we believe suffer breakage as a result of
> > > recent ITP changes) stores the users choice of IdP in localStorage at
> > > seamlessaccess.org
> > 
> > Does this mean the user goes to seamlessaccess.org as first-party website
> > and log in there? Do users then revisit seamlessaccess.org or is the login
> > kind of a one-time thing?
> > 
> 
> The user is redirected from the site to service.seamlessaccess.org (a SAML
> identity provider discovery request to be precise) and does a search for
> their IdP and selects it.

This means user interaction on seamlessaccess.org which is important.

> The user is redirected back to the site with the
> URL of the IdP and the site then issues an authentication request to the IdP
> (SAML in our case but openidc would look the same since we don't do
> email-style webfinger discovery for privacy reasons). When the user picks
> the IdP the URL is stored in localStorage on service.seamlessaccess.org.

This will be stored in first-party LocalStorage which in the case of WebKit is persistent.

> Note that what happens at service.seamlessacces.org isn't actually a login
> but a selection of an IdP.

Are these IdPs well-known ones or custom ones for your users? I'm thinking through how existing ITP behavior will work with these IdPs. (BTW, I assume IdP is short for Identity Provider.)

> In some metaphysical sense I guess you could say
> that the user "logs on" to service.seamlessaccess.org by doing the IdP
> selection but this doesn't create any user-specific state anywhere.
> 
> > > and we provide a component for inclusion on sites which
> > > makes it possible for users to initiate a login flow.
> > 
> > How does this component work? Is it an iframe from seamlessaccess.org or
> > some other subresource from seamlessaccess.org?
> 
> it is an iframe from service.seamlessaccess.org/cta which in turn pulls in
> an iframe from service.seamlessaccess.org/ps which acually accesses the
> localStorage.

In WebKit, this iframe will have its LocalStorage partitioned (double-keyed off of the first-party) and thus will not have access to the LocalStorage set when the user picked the IdP on service.seamlessaccess.org. This has been the case by default since 2013.

Have you tested your service in Safari? If you find that it works there, the flow has to be different since Safari (actually WebKit in Safari) does not allow a third-party iframe to access its first-party LocalStorage. Or I am misunderstanding something in your flow.

> The idea is that users who almost never switch IdPs should have to go
> through the IdP selection dialog every day to login.
> 
> I am aware that some (I heard this from John Bradley) have suggested using a
> variation of payment providers to represent IdP selections in the browser.
> This comes pretty close to what we're trying to achive here except that our
> "payment providers" don't come with any personal information - its just a
> generic URL for the IdP.
> 
> > 
> > How does the login flow work? Does it take the user to seamlessaccess.org
> > for confirmation and then back to the relying party with some token? Or does
> > the login flow happen in an embedded fashion on the relying party's website?
> 
> The actual login flow happens between the relying partys website and the
> users chosen IdP. No user token is passed back to the RP website - just the
> IdPs URL that comes back to the RPs website.
Comment 5 Leif Johansson 2020-03-26 15:28:14 PDT
> 
> This means user interaction on seamlessaccess.org which is important.
> 

indeed

> > The user is redirected back to the site with the
> > URL of the IdP and the site then issues an authentication request to the IdP
> > (SAML in our case but openidc would look the same since we don't do
> > email-style webfinger discovery for privacy reasons). When the user picks
> > the IdP the URL is stored in localStorage on service.seamlessaccess.org.
> 
> This will be stored in first-party LocalStorage which in the case of WebKit
> is persistent.

yes

> 
> > Note that what happens at service.seamlessacces.org isn't actually a login
> > but a selection of an IdP.
> 
> Are these IdPs well-known ones or custom ones for your users? I'm thinking
> through how existing ITP behavior will work with these IdPs. (BTW, I assume
> IdP is short for Identity Provider.)
> 
> > In some metaphysical sense I guess you could say
> > that the user "logs on" to service.seamlessaccess.org by doing the IdP
> > selection but this doesn't create any user-specific state anywhere.
> > 
> > > > and we provide a component for inclusion on sites which
> > > > makes it possible for users to initiate a login flow.
> > > 
> > > How does this component work? Is it an iframe from seamlessaccess.org or
> > > some other subresource from seamlessaccess.org?
> > 
> > it is an iframe from service.seamlessaccess.org/cta which in turn pulls in
> > an iframe from service.seamlessaccess.org/ps which acually accesses the
> > localStorage.
> 
> In WebKit, this iframe will have its LocalStorage partitioned (double-keyed
> off of the first-party) and thus will not have access to the LocalStorage
> set when the user picked the IdP on service.seamlessaccess.org. This has
> been the case by default since 2013.

are you saying the first iframe (the button) /would/ have access to LocalStorage from service.seamlessaccess.org?

> 
> Have you tested your service in Safari? If you find that it works there, the
> flow has to be different since Safari (actually WebKit in Safari) does not
> allow a third-party iframe to access its first-party LocalStorage. Or I am
> misunderstanding something in your flow.
> 

Thats interesting. We will do more testing to verify!
Comment 6 John Wilander 2020-03-26 15:56:55 PDT
(In reply to Leif Johansson from comment #5)
> > 
> > This means user interaction on seamlessaccess.org which is important.
> > 
> 
> indeed
> 
> > > The user is redirected back to the site with the
> > > URL of the IdP and the site then issues an authentication request to the IdP
> > > (SAML in our case but openidc would look the same since we don't do
> > > email-style webfinger discovery for privacy reasons). When the user picks
> > > the IdP the URL is stored in localStorage on service.seamlessaccess.org.
> > 
> > This will be stored in first-party LocalStorage which in the case of WebKit
> > is persistent.
> 
> yes
> 
> > 
> > > Note that what happens at service.seamlessacces.org isn't actually a login
> > > but a selection of an IdP.
> > 
> > Are these IdPs well-known ones or custom ones for your users? I'm thinking
> > through how existing ITP behavior will work with these IdPs. (BTW, I assume
> > IdP is short for Identity Provider.)
> > 
> > > In some metaphysical sense I guess you could say
> > > that the user "logs on" to service.seamlessaccess.org by doing the IdP
> > > selection but this doesn't create any user-specific state anywhere.
> > > 
> > > > > and we provide a component for inclusion on sites which
> > > > > makes it possible for users to initiate a login flow.
> > > > 
> > > > How does this component work? Is it an iframe from seamlessaccess.org or
> > > > some other subresource from seamlessaccess.org?
> > > 
> > > it is an iframe from service.seamlessaccess.org/cta which in turn pulls in
> > > an iframe from service.seamlessaccess.org/ps which acually accesses the
> > > localStorage.
> > 
> > In WebKit, this iframe will have its LocalStorage partitioned (double-keyed
> > off of the first-party) and thus will not have access to the LocalStorage
> > set when the user picked the IdP on service.seamlessaccess.org. This has
> > been the case by default since 2013.
> 
> are you saying the first iframe (the button) /would/ have access to
> LocalStorage from service.seamlessaccess.org?

None of the iframes will have access to first-party LocalStorage if they are third-party iframes, i.e. loaded under a first-party website that is not *.seamlessaccess.org. The reason is that third-party LocalStorage is partitioned per first-party site in WebKit.

An iframe from seamlessaccess.org under news.example will have one instance of LocalStorage. An iframe from seamlessaccess.org under bank.example will have another instance of LocalStorage. None of those two instances are shared with the first-party LocalStorage for seamlessaccess.org.

Also, WebKit's third-party LocalStorage is ephemeral so it automatically goes away when the browser is restarted.

> > Have you tested your service in Safari? If you find that it works there, the
> > flow has to be different since Safari (actually WebKit in Safari) does not
> > allow a third-party iframe to access its first-party LocalStorage. Or I am
> > misunderstanding something in your flow.
> > 
> 
> Thats interesting. We will do more testing to verify!

Sounds good!
Comment 7 Leif Johansson 2020-03-27 06:09:53 PDT
So following onto Johns excellent analysis. My takeaway is that there is no way for our approach to work in safari which gets me back to my original question:

Is there any way for seamlessaccess.org to allow sites to learn about the users IdP selection - conditioned on a user gesture indicating a desire to login - without involving a redirect to seamlessaccess.org ?
Comment 8 John Wilander 2020-03-27 10:21:26 PDT
(In reply to Leif Johansson from comment #7)
> So following onto Johns excellent analysis. My takeaway is that there is no
> way for our approach to work in safari which gets me back to my original
> question:
> 
> Is there any way for seamlessaccess.org to allow sites to learn about the
> users IdP selection - conditioned on a user gesture indicating a desire to
> login - without involving a redirect to seamlessaccess.org ?

I think your best shot is the Storage Access API. You already have a third-party iframe which can drive this. The user granting storage access counts as first-party interaction and so it'll also reset the timestamp for when LocalStorage for seamlessaccess.org would happen.

However, the Storage Access API only opens up access to first-party cookies, not LocalStorage or other HTML storage. It's purpose is to allow third-parties to get to authentication state which is typically held in cookies.

There are links to the Storage Access API in the blog post, including one to the ongoing standardization process where it's discussed with other browser vendors and service providers on the web.
Comment 9 Leif Johansson 2020-03-28 15:44:10 PDT
That approach would require us to maintain state for the user in a service component which clearly implies *less* user privacy than we achieve with other browser platforms.
Comment 10 John Wilander 2020-03-28 16:13:38 PDT
(In reply to Leif Johansson from comment #9)
> That approach would require us to maintain state for the user in a service
> component which clearly implies *less* user privacy than we achieve with
> other browser platforms.

If you have to use LocalStorage or IndexedDB to achieve your goals, you have to take the user to your website as first party. That has been the case in Safari for seven years and has not changed due to ITP. If you do that navigation, you also have an opportunity to get user interaction as first-party which gives the user a chance to see you and be reminded that your service is involved in their login flow.

Another way of doing it is to use cookies in some clever way. I don’t know the design of your features to say how but it could be an option.
Comment 11 Leif Johansson 2020-03-29 23:31:23 PDT
(In reply to John Wilander from comment #10)
> (In reply to Leif Johansson from comment #9)
> > That approach would require us to maintain state for the user in a service
> > component which clearly implies *less* user privacy than we achieve with
> > other browser platforms.
> 
> If you have to use LocalStorage or IndexedDB to achieve your goals, you have
> to take the user to your website as first party. That has been the case in
> Safari for seven years and has not changed due to ITP. If you do that
> navigation, you also have an opportunity to get user interaction as
> first-party which gives the user a chance to see you and be reminded that
> your service is involved in their login flow.

OK now I'm confused. We *do* send the user to service.seamlessaccess.org as a first party! The visit *does* involve interaction and the user clearly understands this is a part of the login flow. The question is how we can leverage this first-party visit to display (even if it is just for a time) their choice on other websites via iframes /after/ the first initial visit.

> 
> Another way of doing it is to use cookies in some clever way. I don’t know
> the design of your features to say how but it could be an option.

We could certainly build the same mechanism using cookies but it would (and we have actually tested this) imply subjecting the user to more privacy risk than we do today partly because we would have to maintain state for each user in a central service which would then become a huge privacy attack target.

On a side-note we are looking at why our users believe this has worked in Safari before and it is possible that several of of our users had already turned on 3rd party access in Safari settings (not because we told them to!)

Googling the issue one readily finds evidence of several sites who advise users on how to "manage" Safari settings. Do you have any data to suggest if this is indeed a common practice by users?
Comment 12 John Wilander 2020-03-31 15:40:40 PDT
(In reply to Leif Johansson from comment #11)
> (In reply to John Wilander from comment #10)
> > (In reply to Leif Johansson from comment #9)
> > > That approach would require us to maintain state for the user in a service
> > > component which clearly implies *less* user privacy than we achieve with
> > > other browser platforms.
> > 
> > If you have to use LocalStorage or IndexedDB to achieve your goals, you have
> > to take the user to your website as first party. That has been the case in
> > Safari for seven years and has not changed due to ITP. If you do that
> > navigation, you also have an opportunity to get user interaction as
> > first-party which gives the user a chance to see you and be reminded that
> > your service is involved in their login flow.
> 
> OK now I'm confused. We *do* send the user to service.seamlessaccess.org as
> a first party! The visit *does* involve interaction and the user clearly
> understands this is a part of the login flow. The question is how we can
> leverage this first-party visit to display (even if it is just for a time)
> their choice on other websites via iframes /after/ the first initial visit.

What I was trying to say was, if you have to use LocalStorage or IndexedDB to achieve your goals, you have to take the user to your website as first party *every time*.

LocalStorage is permanently partitioned in WebKit and has been for seven years. A third-party cannot get to its first-party LocalStorage in WebKit. It was deemed a cross-site tracking vector back in 2011-2012 and partitioning was enforced.
> > Another way of doing it is to use cookies in some clever way. I don’t know
> > the design of your features to say how but it could be an option.
> 
> We could certainly build the same mechanism using cookies but it would (and
> we have actually tested this) imply subjecting the user to more privacy risk
> than we do today partly because we would have to maintain state for each
> user in a central service which would then become a huge privacy attack
> target.

What I'm saying is that cookies can also serve as client-side storage. They are certainly not ideal for client-side storage since they are sent in requests, but they can work as such.

> On a side-note we are looking at why our users believe this has worked in
> Safari before and it is possible that several of of our users had already
> turned on 3rd party access in Safari settings (not because we told them to!)
> 
> Googling the issue one readily finds evidence of several sites who advise
> users on how to "manage" Safari settings. Do you have any data to suggest if
> this is indeed a common practice by users?

We always advise our users to keep security and privacy settings enabled.
Comment 13 Raoul Teeuwen 2020-03-31 22:33:12 PDT
Seeing the discussion, i wonder whether a VC, demo-ing a flow and showing what Seamless Access is supposed to improve for the user, could help?
Comment 14 John Wilander 2020-04-01 08:12:01 PDT
(In reply to Raoul Teeuwen from comment #13)
> Seeing the discussion, i wonder whether a VC, demo-ing a flow and showing
> what Seamless Access is supposed to improve for the user, could help?

I believe I have an understanding of how it works from Leif’s description.

The important thing now is to first understand if and how their service has worked in Safari the last seven years since the description of combined first and third party LocalStorage usage means it cannot have worked.
Comment 15 Leif Johansson 2020-04-01 08:21:35 PDT
> What I was trying to say was, if you have to use LocalStorage or IndexedDB
> to achieve your goals, you have to take the user to your website as first
> party *every time*.
> 

Much clearer. This is of course the current fallback for safari for seamlessaccess.org. 


> What I'm saying is that cookies can also serve as client-side storage. They
> are certainly not ideal for client-side storage since they are sent in
> requests, but they can work as such.
> 

Indeed. We may have to look at something like that but it would be much
better if browsers would have adopted a native mechanism for facilitating 
identity discovery and other identity-related flows before turning 
responsible identity management services into collateral damage.

> 
> We always advise our users to keep security and privacy settings enabled.

I am sure. I was curious if you have telemetry to suggest insight into what 
users actually do.
Comment 16 Leif Johansson 2020-04-01 08:30:05 PDT
(In reply to John Wilander from comment #14)
> (In reply to Raoul Teeuwen from comment #13)
> > Seeing the discussion, i wonder whether a VC, demo-ing a flow and showing
> > what Seamless Access is supposed to improve for the user, could help?
> 
> I believe I have an understanding of how it works from Leif’s description.
> 
> The important thing now is to first understand if and how their service has
> worked in Safari the last seven years since the description of combined
> first and third party LocalStorage usage means it cannot have worked.

I believe John is probably correct here. This never worked in safari and the only reason we never got complaints (please don't be offended by the implication that we focus browser testing elsewhere) may be because some users have enabled 3rd party access manually.