Created attachment 395994 [details] Simple application diagram First of all, my apologies for a long post. I'm a noob to ITP and can't figure out a problem that is most likely due to my misunderstanding of its rules. With the release of Safari 13.1 our application's SSO broke, and I've spent the last week reading webkit blog, webkit bugzilla and various other channels. I'm stuck and have nowhere else to reach for help, so I really appreciate any advice in advance! ## Details Our main application is hosted on mainapp.example.ca and contains an iframe hosted on subframe.example.ca. The iframe needs to be able to call services on both *.example.ca and *.example.com domains. First, a user logs into the main application on mainapp.example.ca. The application authenticates against an SSO endpoint hosted on sso.example.ca, which returns an authentication cookie like: `Set-Cookie: auth=...; path=/; domain=.example.ca; secure; samesite=none; HttpOnly`. The browser is then sent to sso.example.com/copy which copies the authentication cookie from .ca to .com domain: `Set-Cookie: auth=...; path=/; domain=.example.com; secure; samesite=none; HttpOnly` and responds with a 302 redirect back to the main application. Now the user is logged in and inside the application, they reach a page which has an iframe hosted on subframe.example.ca that makes several network calls to various endpoints on api.example.ca and api.example.com domains. I see that the calls to api.example.ca has authentication cookie, but api.example.com doesn't, so they fail. The cookie used to pass through in Safari <= 13.0.5, and also works fine in Chrome and Firefox, but starting with Safari 13.1 it stopped working. If I disable ITP through Experimental features, everything works as expected in Safari 13.1 After finding the [recent blog post on webkit.org](https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/) regarding full third party cookie blocking in Safari 13.1, I started looking into the Storage Access API, but not getting anywhere with it. I've tried calling it from the top frame and from the inner iframe and not able to get access or a popup asking me for access: `document.hasStorageAccess()` called from the top frame always resolves to `true`. `document.requestStorageAccess()` called from the top frame always resolves without a popup. `document.hasStorageAccess()` called within the subframe always resolve to `false`. `document.requestStorageAccess()` called within the subframe always rejects without value and without a popup. I've tried adding an explicit user gesture. I've added a button within the iframe that triggers the above methods before any network calls are made but still got the same results. I've read that a redirect is not enough for ITP, so I tried to explicitly interacting with the SSO sites and manually logging in on sso.example.com, as well as sso.example.ca, before I login on the main application, but the results are still the same. Each time I try something new I make sure to Clear all history and restart Safari before I do anything. ITP debug mode is not providing much information. I only see the same message over and over again: ``` 2020-04-09 11:22:13.779214-0400 0xeca56 Info 0x0 57786 0 com.apple.WebKit.Networking: (WebKit) [com.apple.WebKit:ITPDebug] Done updating cookie blocking. 2020-04-09 11:22:15.340601-0400 0xeca55 Info 0x0 57786 0 com.apple.WebKit.Networking: (WebKit) [com.apple.WebKit:ITPDebug] Done updating cookie blocking. 2020-04-09 11:22:19.444489-0400 0xeca58 Info 0x0 57786 0 com.apple.WebKit.Networking: (WebKit) [com.apple.WebKit:ITPDebug] Done updating cookie blocking. ``` Starting with Safari Technology Preview 104 I see a couple of more additional logs related to the redirect: ``` 2020-04-08 17:17:56.151289-0400 0x9ca43 Info 0x0 80926 0 com.apple.WebKit.Networking: (WebKit) [com.apple.WebKit:ITPDebug] Did set example.ca as making a top frame redirect to example.com. 2020-04-08 17:17:56.416058-0400 0x9ce0f Info 0x0 80926 0 com.apple.WebKit.Networking: (WebKit) [com.apple.WebKit:ITPDebug] Did set example.com as making a top frame redirect to example.ca. ``` Based on this I thought maybe ITP was blocking because of the top frame redirect, so as a test I've removed the redirect altogether, but still get the same results. Luckily, I'm able to run our iframed application standalone on a top frame to test things. Even better, as a test, I can also run it on both, subframe.example.com and subframe.example.ca domains, which allowed me to simplify the flow as much a possible. I was able to remove the main application and remove the redirects out of the picture altogether to try to isolate the problem, but still didn't get anywhere. I have tried different SameSite cookie settings too. I've tried None, Lax and not setting SameSite at all with no difference. ## Simplified case (TLDR) The simplest case that I was able to get to: 1. Clean all history, restart Safari 2. in a new browser window go to sso.example.ca and login => .example.ca cookies are set 3. go to and login at sso.example.com => .example.com cookies are set 4. go to subframe.example.ca in browser (top frame) => AJAX calls to api.example.ca succeed (has cookies), but calls to api.example.com fail (no cookies) 5. go to subframe.example.com in browser => AJAX calls to api.example.com succeed (has cookies), but calls to api.example.ca fail (no cookies) ## requestStorageAccess rules I've reviewed all the Storage Access API rules: - `If the sub frame is sandboxed but doesn’t have the tokens “allow-storage-access-by-user-activation” and “allow-same-origin”, reject.` ✅The iframe is not sandboxed - `If the sub frame’s parent is not the top frame, reject.` ✅The sub frame's parent mainapp.example.ca is the top frame, while subframe.example.ca iframe is the direct child of mainapp.example.ca - `If the browser is not processing a user gesture, reject.` ✅I've tried adding a button on subframe.example.ca within the subframe and triggering the requestStorageAccess() call in the click handler of that button to have an explicit user gesture, but saw no change in behavior: hasStorageAccess() resolves with false, requestStorageAccess() rejects without value and no popup from the browser asking me to grant access. - `If the sub frames eTLD+1 is equal to the top frame’s eTLD+1, resolve.` ✅Subframe at subframe.example.ca is on the same eTLD+1 as the top frame on mainapp.example.ca - `If the sub frame’s origin’s cookies are currently blocked, reject. This means that ITP has either purged the origin’s website data or will do so in the near future. Thus there is no storage to get access to.` ❓I have no way of telling if or why the cookies have been purged. I know that the browser does have both sets of cookies because calls to .com services work from .com site and calls to .ca services work from .ca site. - `If all the above has passed, resolve.` ❌Does not resolve ## Browsers tested ✅Chrome 80 works ✅Firefox 75 works ✅Safari 13.0.5 works ❌Safari 13.1 doesn't work ❌Safari Technology Preview 104 doesn't work Any help would be greatly appreciated!
<rdar://problem/61535579>
Hi! Thank you for filing! *.example.com having its cookie access blocked when third-party under *.example.ca is intentional which you probably know from reading the latest ITP blog post. Here's what you can do if you want to make use of the Storage Access API: 1. When you navigate the top frame to *.example.com and set its authentication cookie, don't just redirect back to *.example.ca because doing so means *.example.com is behaving like a bounce tracker. Instead stop at *.example.com and have the user interact with the *.example.com website. This could be a confirm button or such, and gives the user a chance to see the *.example.com and understand that it is involved in the *.example.ca functionality. Make sure to set the authentication cookie while on *.example.com as first-party website since third-parties without pre-existing cookies cannot set cookies in Safari. 2. Take the user back to *.example.ca and serve a third-party iframe from *.example.com on that page. 3. Have the user interact with the third-party iframe from *.example.com under *.example.ca. This could be tapping/clicking on a button in the iframe. 4. On the event handler of that tap/click in the third-party iframe from *.example.com, you should see Safari prompt the user and ask if they are willing to allow storage access to *.example.com under *.example.ca. 5. If the user opts in, the iframe from *.example.com now should have cookie access. It can navigate same-site and still maintain cookie access. However, when the iframe goes away, so does its storage access. 6. Subsequent taps/clicks on third-party iframes from *.example.com under. *.example.ca which call the Storage Access API on the event handler will not prompt the user since the user has already opted in. Instead, storage access will be granted immediately. Let me know if the above works for you. Thanks!
(In reply to John Wilander from comment #2) > Hi! > > Thank you for filing! > > *.example.com having its cookie access blocked when third-party under > *.example.ca is intentional which you probably know from reading the latest > ITP blog post. > > Here's what you can do if you want to make use of the Storage Access API: > > 1. When you navigate the top frame to *.example.com and set its > authentication cookie, don't just redirect back to *.example.ca because > doing so means *.example.com is behaving like a bounce tracker. Instead stop > at *.example.com and have the user interact with the *.example.com website. > This could be a confirm button or such, and gives the user a chance to see > the *.example.com and understand that it is involved in the *.example.ca > functionality. Make sure to set the authentication cookie while on > *.example.com as first-party website since third-parties without > pre-existing cookies cannot set cookies in Safari. > > 2. Take the user back to *.example.ca and serve a third-party iframe from > *.example.com on that page. > > 3. Have the user interact with the third-party iframe from *.example.com > under *.example.ca. This could be tapping/clicking on a button in the iframe. > > 4. On the event handler of that tap/click in the third-party iframe from > *.example.com, you should see Safari prompt the user and ask if they are > willing to allow storage access to *.example.com under *.example.ca. Sorry, I meant to say you call document.requestStorageAccess() on that event handler and then should expect to see the prompt. > 5. If the user opts in, the iframe from *.example.com now should have cookie > access. It can navigate same-site and still maintain cookie access. However, > when the iframe goes away, so does its storage access. > > 6. Subsequent taps/clicks on third-party iframes from *.example.com under. > *.example.ca which call the Storage Access API on the event handler will not > prompt the user since the user has already opted in. Instead, storage access > will be granted immediately. > > Let me know if the above works for you. Thanks!
(In reply to John Wilander from comment #2) Thank you, John! I'll give it a try. Meanwhile, can you clarify this point: > Make sure to set the authentication cookie while on > *.example.com as first-party website since third-parties without > pre-existing cookies cannot set cookies in Safari. How would I specifically set authentication cookie as first-party website (as opposed to third-party) while on *.example.com? Is there somewhere I can see the differentiation in devtools or elsewhere? The rest seems pretty clear. I'll report back in a couple of days with results, once I'm able to set it up.
(In reply to Dmitriy T from comment #4) > (In reply to John Wilander from comment #2) > > Thank you, John! I'll give it a try. Meanwhile, can you clarify this point: > > > Make sure to set the authentication cookie while on > > *.example.com as first-party website since third-parties without > > pre-existing cookies cannot set cookies in Safari. > > How would I specifically set authentication cookie as first-party website > (as opposed to third-party) while on *.example.com? Is there somewhere I can > see the differentiation in devtools or elsewhere? Let's say *.example.com doesn't yet have any cookies set and the user is on *.example.ca, meaning *.example.ca is showing in the URL bar. If a third-party request to *.example.com under that webpage receives a response with a Set-Cookie header, that incoming cookie will not be accepted. This has been the case in Safari since version 1.0 in 2003. What I'm saying is, when you navigate the user to *.example.com and have them interact with *.example.com as first party website, also make sure to set your authentication cookie *.example.com while there. I believe you said you navigate there to set the authentication cookie, right? The reason is that if you go back to *.example.ca before *.example.com has set any cookies, it will not be able to set any cookies regardless of calls to the Storage Access API since third-parties without pre-existing cookies can never set cookies in Safari. > The rest seems pretty clear. I'll report back in a couple of days with > results, once I'm able to set it up. Thank you!
(In reply to John Wilander from comment #2) > Hi! > > Thank you for filing! > > *.example.com having its cookie access blocked when third-party under > *.example.ca is intentional which you probably know from reading the latest > ITP blog post. > > Here's what you can do if you want to make use of the Storage Access API: > > 1. When you navigate the top frame to *.example.com and set its > authentication cookie, don't just redirect back to *.example.ca because > doing so means *.example.com is behaving like a bounce tracker. Instead stop > at *.example.com and have the user interact with the *.example.com website. > This could be a confirm button or such, and gives the user a chance to see > the *.example.com and understand that it is involved in the *.example.ca > functionality. Make sure to set the authentication cookie while on > *.example.com as first-party website since third-parties without > pre-existing cookies cannot set cookies in Safari. > > 2. Take the user back to *.example.ca and serve a third-party iframe from > *.example.com on that page. > > 3. Have the user interact with the third-party iframe from *.example.com > under *.example.ca. This could be tapping/clicking on a button in the iframe. > > 4. On the event handler of that tap/click in the third-party iframe from > *.example.com, you should see Safari prompt the user and ask if they are > willing to allow storage access to *.example.com under *.example.ca. > > 5. If the user opts in, the iframe from *.example.com now should have cookie > access. It can navigate same-site and still maintain cookie access. However, > when the iframe goes away, so does its storage access. > > 6. Subsequent taps/clicks on third-party iframes from *.example.com under. > *.example.ca which call the Storage Access API on the event handler will not > prompt the user since the user has already opted in. Instead, storage access > will be granted immediately. > > Let me know if the above works for you. Thanks! I've tried, and unfortunately still no luck :( Here's what I have tried. It is the same as you've described, aside from the redirect, which is currently difficult to do in the way you've described it, so I removed it out of the picture because I can login directly on the sso.example.com website, so: 1) Go to sso.example.com and login (explicit user interaction, typed in username/password and logged in) -> .example.com cookies are set as first-party 2) Go to mainapp.example.ca and login (explicit user interaction, typed in the same username/password and logged in) -> .example.ca cookies are set as first-party 3) Continue to the next page on mainapp.example.ca, which has an iframe with source subframe.example.com The only thing within that iframe iframe has is a button. (side note: I thought parent and subframe are supposed to be on the same eTLD+1 according to the rules, which I had originally, but I followed your instructions and changed that to be on different eTLDs) 4) Click the button within the iframe. The button click calls hasStorageAccess() -> resolves false. Calls requestStorageAccess() -> rejected. No popup. Tries to call api.example.com - cookies are still not sent. If I open subframe.example.com as a top frame in a new window and click the same button. Calls to hasStorageAccess() resolves to true. Calls to api.example.com have cookies.
(In reply to Dmitriy T from comment #6) > (In reply to John Wilander from comment #2) > > Hi! > > > > Thank you for filing! > > > > *.example.com having its cookie access blocked when third-party under > > *.example.ca is intentional which you probably know from reading the latest > > ITP blog post. > > > > Here's what you can do if you want to make use of the Storage Access API: > > > > 1. When you navigate the top frame to *.example.com and set its > > authentication cookie, don't just redirect back to *.example.ca because > > doing so means *.example.com is behaving like a bounce tracker. Instead stop > > at *.example.com and have the user interact with the *.example.com website. > > This could be a confirm button or such, and gives the user a chance to see > > the *.example.com and understand that it is involved in the *.example.ca > > functionality. Make sure to set the authentication cookie while on > > *.example.com as first-party website since third-parties without > > pre-existing cookies cannot set cookies in Safari. > > > > 2. Take the user back to *.example.ca and serve a third-party iframe from > > *.example.com on that page. > > > > 3. Have the user interact with the third-party iframe from *.example.com > > under *.example.ca. This could be tapping/clicking on a button in the iframe. > > > > 4. On the event handler of that tap/click in the third-party iframe from > > *.example.com, you should see Safari prompt the user and ask if they are > > willing to allow storage access to *.example.com under *.example.ca. > > > > 5. If the user opts in, the iframe from *.example.com now should have cookie > > access. It can navigate same-site and still maintain cookie access. However, > > when the iframe goes away, so does its storage access. > > > > 6. Subsequent taps/clicks on third-party iframes from *.example.com under. > > *.example.ca which call the Storage Access API on the event handler will not > > prompt the user since the user has already opted in. Instead, storage access > > will be granted immediately. > > > > Let me know if the above works for you. Thanks! > > I've tried, and unfortunately still no luck :( > > Here's what I have tried. It is the same as you've described, aside from the > redirect, which is currently difficult to do in the way you've described it, > so I removed it out of the picture because I can login directly on the > sso.example.com website, so: > > 1) Go to sso.example.com and login (explicit user interaction, typed in > username/password and logged in) -> .example.com cookies are set as > first-party > > 2) Go to mainapp.example.ca and login (explicit user interaction, typed in > the same username/password and logged in) -> .example.ca cookies are set as > first-party > > 3) Continue to the next page on mainapp.example.ca, which has an iframe with > source subframe.example.com The only thing within that iframe iframe has is > a button. (side note: I thought parent and subframe are supposed to be on > the same eTLD+1 according to the rules, which I had originally, but I > followed your instructions and changed that to be on different eTLDs) > > 4) Click the button within the iframe. The button click calls > hasStorageAccess() -> resolves false. Calls requestStorageAccess() -> > rejected. No popup. Tries to call api.example.com - cookies are still not > sent. document.hasStorageAccess() does not require user interaction. You can call it whenever you want so that you can make a decision as to whether or not you need to request storage access. However, since it's asynchronous, it will consume the user gesture if you call it on e.g. a click handler. Only call document.requestStorageAccess() on the event handler. That's the API which requires a user gesture. > If I open subframe.example.com as a top frame in a new window and click the > same button. Calls to hasStorageAccess() resolves to true. Calls to > api.example.com have cookies.
(In reply to John Wilander from comment #7) > ... since it's asynchronous, it > will consume the user gesture if you call it on e.g. a click handler. > > Only call document.requestStorageAccess() on the event handler. That's the > API which requires a user gesture. > That was it! I never thought that the promise from the first call would swallow the gesture. 🤦🏼♂️ Even Mozilla docs suggest it to be called this way: https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API/Using#Accessing_a_user's_cookies_in_an_embedded_cross-origin_iframe I wish the API provided a clear reason for rejection. With the ITPDebug logging lacking, no reason for rejections and a number of very specific rules for access, it is next to impossible to debug it right now. I'll submit a request for improvement in the github repo for this. Thanks a lot for your help, John!
John, One more question. Is there somewhere I can get more information about this option from the recent blog post (https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/): > Option 1: OAuth 2.0 Authorization with which the authenticating domain (in your case, the third-party that expects cookies) forwards an authorization token to your website which you consume and use to establish a first-party login session with a server-set Secure and HttpOnly cookie. The general oAuth suggestion/consensus is to store and pass the token in a Secure and HttpOnly cookie (as opposed to storing it in the Web Storage), but Safari won't pass the cookie because it's considered third-party. How do I establish a first-party login session within third-party context? For example, since my subframe.example.ca has first-party access, I can always get an auth token from sso.exmaple.ca, which I can pass in an Authorization header with the network requests to api.example.com, but where can I store this token within the iframe? It seems that my only options are the Web Storage or a client-side cookie, but both are discouraged for security reasons, so it's a catch-22 🤷🏼♂️
We are seeing issue when we have an iframe application that sets the cookie with the samesite=none;secure;HttpOnly, webkit (Safari 13.1) is not respecting that setting and does not send the next request from the iframe with the cookie. This is causing authentication loops with no clear workaround. What can be done to fix this without requiring all their customers to change the settings on their browsers? This seems to violate the RFC- https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-05#page-27 4.1.2.7. The SameSite Attribute if it is set to 'none', it should be sent with same and cross site calls. in this case, it is only considered cross-site because it is in an iframe although the call is to the same site in the iframe.
We are seeing issue when we have an iframe application that sets the cookie with the samesite=none;secure;HttpOnly, webkit (Safari 13.1) is not respecting that setting and does not send the next request from the iframe with the cookie. This is causing authentication loops with no clear workaround. What can be done to fix this without requiring all their customers to change the settings on their browsers? This seems to violate the RFC- https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-05#page-27 4.1.2.7. The SameSite Attribute https://tools.ietf.org/html/draft-west-cookie-incrementalism-00 if it is set to 'none', it should be sent with same and cross site calls. in this case, it is only considered cross-site because it is in an iframe although the call is to the same site in the iframe.
(In reply to Westley from comment #10) > We are seeing issue when we have an iframe application that sets the cookie > with the samesite=none;secure;HttpOnly, webkit (Safari 13.1) is not > respecting that setting and does not send the next request from the iframe > with the cookie. This is causing authentication loops with no clear > workaround. What can be done to fix this without requiring all their > customers to change the settings on their browsers? > > This seems to violate the RFC- > https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-05#page-27 > 4.1.2.7. The SameSite Attribute > > if it is set to 'none', it should be sent with same and cross site calls. > in this case, it is only considered cross-site because it is in an iframe > although the call is to the same site in the iframe. Hi! As of Safari 13.1, all third-party cookies are blocked by default. This is part of the Intelligent Tracking Prevention feature. You can read about the latest update and you options for login across websites here: https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/ . See specifically “Developer Guidance.”
Is there any way for Dmitriy to add his sites to some kind of well-known list? This list could inform Webkit that "*.example.com" and "*.example.ca" are delivered by the same entity, and cross-domain communications are functional, not for tracking. I suppose this is the opposite of the Public Suffix List in effect.
I must echo Dmitriy's point that this is incredibly hard to debug at the moment - especially for a windows user that cannot debug Safari 13.1. I've been experimenting for a few days and I've only managed to get the dialog to come up a few times. I'm not sure if it has been removed today? However, it seems now that it's actually impossible to add third party cookies unless the example.com level matches? This thread has example.ca, but I don't think that should work now? If that's true, I think it's a crazy decision to make. I know that iframes are used in marketing and it's not an ideal technology to use, but there are still plenty of plugins and the like which make use of them. For some scenarios, the iframe is still the best choice and this will kill them off, for little gain. Hopefully I'm wrong or it's an oversight!
(In reply to Mike Senn from comment #13) > Is there any way for Dmitriy to add his sites to some kind of well-known > list? This list could inform Webkit that "*.example.com" and "*.example.ca" > are delivered by the same entity, and cross-domain communications are > functional, not for tracking. > > I suppose this is the opposite of the Public Suffix List in effect. There is no existing list. We proposed something like it in 2017 but there was almost no interest from other browsers. More recently, Google has proposed the same thing under the name First Party Sets. It still sits in a personal repository so it doesn’t have any real proposal status yet. The idea of such a list looks good on the surface but is riddled with concerns. You can see what we mean in the issue we filed in August last year: https://github.com/krgovind/first-party-sets/issues/6 The country-specific TLD has the best chance of working in my view since it’s the same registrable domain.
(In reply to GB from comment #14) > I must echo Dmitriy's point that this is incredibly hard to debug at the > moment - especially for a windows user that cannot debug Safari 13.1. > > I've been experimenting for a few days and I've only managed to get the > dialog to come up a few times. I'm not sure if it has been removed today? > > However, it seems now that it's actually impossible to add third party > cookies unless the example.com level matches? As mentioned above, all third-party cookies are blocked by default. The blog post outlines three path to deal with it, including the Storage Access API which is purpose built for cross-site iframes. > This thread has example.ca, but I don't think that should work now? > > If that's true, I think it's a crazy decision to make. I know that iframes > are used in marketing and it's not an ideal technology to use, but there are > still plenty of plugins and the like which make use of them. For some > scenarios, the iframe is still the best choice and this will kill them off, > for little gain. > > Hopefully I'm wrong or it's an oversight! Blocking third-party cookies is not specifically about marketing or ads. Please see our tracking prevention policy for details: https://webkit.org/tracking-prevention-policy/ You should expect all modern browsers to block third-party cookies down the road.
Hi John, I have been looking into the options and managed to get the storage access API to work between two sites on different sub-domains, however, it just doesn't work when the two domains are different. I have a product, which is an ecommerce shop that runs as an iframe for small business sites. It works for them because it's quick and easy to setup and at a much lower cost than building their own solution. We use the cookies to link the customer to the basket - clearly nothing to do with tracking or privacy. Looking at the predicament we might need a complex sub-domain strategy, utilising other peoples' DNS records or hacks such as tagging basket ids to the Url (not great!). What is the reason for blocking storage requests from different domains? I'll admit it'll be a poor user experience to have a "scary" pop-up saying that the site needs to access your cookies and they might use them to track you... but it's better than nothing. Or is it that I'm missing an extra step that allows storage requests from different domains?
(In reply to GB from comment #17) > Hi John, > > I have been looking into the options and managed to get the storage access > API to work between two sites on different sub-domains, however, it just > doesn't work when the two domains are different. > > I have a product, which is an ecommerce shop that runs as an iframe for > small business sites. It works for them because it's quick and easy to setup > and at a much lower cost than building their own solution. > > We use the cookies to link the customer to the basket - clearly nothing to > do with tracking or privacy. We often get the comment from various web entities that they don't consider their practice or setup to be "tracking." ITP doesn't judge whether or not a website is tracking or even trying to track users across websites. It prevents the *capability* to track across websites. Say embeddedShop.example is used across ten different websites. If it were allowed to access its cookies or other first party website data while a third-party on those ten websites, it has the capability to cross reference shopping behavior, product interests, time of shopping, level of income, time of day for shopping etc. across those websites without the users having any reasonable chance of knowing that a third-party was involved and had that capability. In Safari, third-parties should not have that capability. > Looking at the predicament we might need a complex sub-domain strategy, > utilising other peoples' DNS records or hacks such as tagging basket ids to > the Url (not great!). > > What is the reason for blocking storage requests from different domains? While "reasons" go more toward a thread model which we have yet to publish, our tracking prevention policy gives a good hint at what you're asking for: https://webkit.org/tracking-prevention-policy/ > I'll admit it'll be a poor user experience to have a "scary" pop-up saying > that the site needs to access your cookies and they might use them to track > you... but it's better than nothing. > > Or is it that I'm missing an extra step that allows storage requests from > different domains? The Storage Access API should work for you. Let's figure it out. 1. Take the user to your shopping domain as first party. This is you reveling yourself and allowing the user a chance to recognize your brand and domain name. 2. Have the user interact with your website as first party. This tells WebKit that the user actually has seen it. I.e. a fraction of a second in a redirect does not count. 3. Set cookies when you are first-party. This establishes the website as "visited" for the purposes of the underlying cookie policy. Third parties without cookies cannot set cookies in Safari and never have since Safari 1.0 in 2003. Now we're ready to use the Storage Access API. 4. Make your cross-site iframe and call document.hasStorgeAccess() as soon as it's rendered to check your status. Don't call this function upon a user gesture since it's asynchronous and will consume the gesture. 5. If your iframe doesn't have storage access, set an event handler on it to call document.requestStorageAccess() on a tap or click. 6. Render the page with your cross-site iframe. Tap or click in the iframe. 7. Choose "Don't Allow" in the prompt (don't choose "Allow" yet because it'll be remembered and you'll have to delete Safari history to reset it). 8. Test the behavior for the "Don't Allow" case. 9. Choose "Allow" in the prompt. 10. Test the behavior for the "Allow" case. I hope I didn't miss something. See if that works for you.
Interact means tap or click. You can use ITP Debug Mode to get information on what the Storage Access API is doing.
Is it possible to tell in the HTTP request whether cookies weren't sent because of ITP, or because it's the user's first visit to the site? If ITP didn't send cookies, I want to use the storage access API and refresh the page if access is granted. If it's the user's first visit, I want to give a 302 redirect to a login portal. Must I use the client-side API to determine which path to take? It seems even the Referer header is removed, so I can't even tell if my content is being iframed or is a top-level page.
(In reply to Mike Senn from comment #20) > Is it possible to tell in the HTTP request whether cookies weren't sent > because of ITP, or because it's the user's first visit to the site? The APIs do their best to obscure this information since the intention is to leak zero or minimal data across websites. > If ITP didn't send cookies, I want to use the storage access API and refresh > the page if access is granted. > > If it's the user's first visit, I want to give a 302 redirect to a login > portal. > > Must I use the client-side API to determine which path to take? It seems > even the Referer header is removed, so I can't even tell if my content is > being iframed or is a top-level page. The referrer is not removed, it's downgraded to origin. The way this works is your iframe checks if you already have storage access. If not, your iframe calls document.requestStorageAccess() on a click event handler. If storage access is granted, the user gesture is persevered so that your iframe can check your cookie status and if the user is not yet logged in, you can directly open a popup to log the user in. Note that storage access is revoked if you navigate the top page. However, the user explicitly granting access is remembered which means subsequent requests to access storage on a click/tap won't prompt the user.
> The Storage Access API should work for you. Let's figure it out. > > 1. Take the user to your shopping domain as first party. This is you > reveling yourself and allowing the user a chance to recognize your brand and > domain name. > 2. Have the user interact with your website as first party. This tells > WebKit that the user actually has seen it. I.e. a fraction of a second in a > redirect does not count. > 3. Set cookies when you are first-party. This establishes the website as > "visited" for the purposes of the underlying cookie policy. Third parties > without cookies cannot set cookies in Safari and never have since Safari 1.0 > in 2003. > > Now we're ready to use the Storage Access API. > > 4. Make your cross-site iframe and call document.hasStorgeAccess() as soon > as it's rendered to check your status. Don't call this function upon a user > gesture since it's asynchronous and will consume the gesture. > 5. If your iframe doesn't have storage access, set an event handler on it to > call document.requestStorageAccess() on a tap or click. > 6. Render the page with your cross-site iframe. Tap or click in the iframe. > 7. Choose "Don't Allow" in the prompt (don't choose "Allow" yet because > it'll be remembered and you'll have to delete Safari history to reset it). > 8. Test the behavior for the "Don't Allow" case. > 9. Choose "Allow" in the prompt. > 10. Test the behavior for the "Allow" case. > > I hope I didn't miss something. See if that works for you. Thanks for the feedback. The missing step for me was visiting the site as a first party and then adding a cookie. At that point I could request and add cookies. The process has become... 1. Customer goes to a page to start the "search for and buy a product" process 2. They click a button/link that takes them to another page on the shop site, which explains the privacy issues and sets a cookie... 3. Clicks another button on that page to go back to the original page 4. The customer interacts with that page 5. The page brings up a dialog asking whether to allow cookies for the shop 6. If they allow it, carry on as normal. Is that actually what you were aiming for? In my opinion... that process is awful! We are better off just having a link to open the site in a new window to buy the products, which has a multitude of it's own downsides. I think you're in danger of making the mistakes of the EU Cookie Law. Enforcing websites to have a clear cookie policy and a way to configure them is not a bad idea, just like these privacy features are not a bad idea... but having a pop-up on every... single... website (That nobody even reads) turned a good idea into a terrible one! I'm sure this privacy stuff is your top priority, but please don't forget about the user experience. As one final question... how long does the storage acceptance continue for (as in the dialog Allow/Deny)? Once it's accepted, I can't get the dialog to appear again. Is there also any way to manually clear it as we do with cookies, etc?
(In reply to John Wilander from comment #12) > (In reply to Westley from comment #10) > > We are seeing issue when we have an iframe application that sets the cookie > > with the samesite=none;secure;HttpOnly, webkit (Safari 13.1) is not > > respecting that setting and does not send the next request from the iframe > > with the cookie. This is causing authentication loops with no clear > > workaround. What can be done to fix this without requiring all their > > customers to change the settings on their browsers? > > > > This seems to violate the RFC- > > https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-05#page-27 > > 4.1.2.7. The SameSite Attribute > > > > if it is set to 'none', it should be sent with same and cross site calls. > > in this case, it is only considered cross-site because it is in an iframe > > although the call is to the same site in the iframe. > > Hi! > > As of Safari 13.1, all third-party cookies are blocked by default. This is > part of the Intelligent Tracking Prevention feature. You can read about the > latest update and you options for login across websites here: > https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/ . > See specifically “Developer Guidance.” In the developer guidance, it links to this- https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies which states that browsers will respect samesite=none, but one browser now needs a workaround.
(In reply to Westley from comment #23) > (In reply to John Wilander from comment #12) > > (In reply to Westley from comment #10) > > > We are seeing issue when we have an iframe application that sets the cookie > > > with the samesite=none;secure;HttpOnly, webkit (Safari 13.1) is not > > > respecting that setting and does not send the next request from the iframe > > > with the cookie. This is causing authentication loops with no clear > > > workaround. What can be done to fix this without requiring all their > > > customers to change the settings on their browsers? > > > > > > This seems to violate the RFC- > > > https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-05#page-27 > > > 4.1.2.7. The SameSite Attribute > > > > > > if it is set to 'none', it should be sent with same and cross site calls. > > > in this case, it is only considered cross-site because it is in an iframe > > > although the call is to the same site in the iframe. > > > > Hi! > > > > As of Safari 13.1, all third-party cookies are blocked by default. This is > > part of the Intelligent Tracking Prevention feature. You can read about the > > latest update and you options for login across websites here: > > https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/ . > > See specifically “Developer Guidance.” > > In the developer guidance, it links to this- > https://developer.mozilla.org/en-US/docs/Web/HTTP/ > Cookies#Secure_and_HttpOnly_cookies which states that browsers will respect > samesite=none, but one browser now needs a workaround. Safari prevents cross-site tracking by default. This is not about "respecting" SameSite=none. Safari blocks third-party cookies. Brave and the Tor browser also block third-party cookies. Other browsers have more relaxed cookie policies. What we are referring to is Secure and HttpOnly cookies. That is our guidance for first and third parties alike.
(In reply to GB from comment #22) > > The Storage Access API should work for you. Let's figure it out. > > > > 1. Take the user to your shopping domain as first party. This is you > > reveling yourself and allowing the user a chance to recognize your brand and > > domain name. > > 2. Have the user interact with your website as first party. This tells > > WebKit that the user actually has seen it. I.e. a fraction of a second in a > > redirect does not count. > > 3. Set cookies when you are first-party. This establishes the website as > > "visited" for the purposes of the underlying cookie policy. Third parties > > without cookies cannot set cookies in Safari and never have since Safari 1.0 > > in 2003. > > > > Now we're ready to use the Storage Access API. > > > > 4. Make your cross-site iframe and call document.hasStorgeAccess() as soon > > as it's rendered to check your status. Don't call this function upon a user > > gesture since it's asynchronous and will consume the gesture. > > 5. If your iframe doesn't have storage access, set an event handler on it to > > call document.requestStorageAccess() on a tap or click. > > 6. Render the page with your cross-site iframe. Tap or click in the iframe. > > 7. Choose "Don't Allow" in the prompt (don't choose "Allow" yet because > > it'll be remembered and you'll have to delete Safari history to reset it). > > 8. Test the behavior for the "Don't Allow" case. > > 9. Choose "Allow" in the prompt. > > 10. Test the behavior for the "Allow" case. > > > > I hope I didn't miss something. See if that works for you. > > Thanks for the feedback. The missing step for me was visiting the site as a > first party and then adding a cookie. At that point I could request and add > cookies. > > The process has become... > 1. Customer goes to a page to start the "search for and buy a product" > process > 2. They click a button/link that takes them to another page on the shop > site, which explains the privacy issues and sets a cookie... > 3. Clicks another button on that page to go back to the original page > 4. The customer interacts with that page > 5. The page brings up a dialog asking whether to allow cookies for the shop > 6. If they allow it, carry on as normal. > > Is that actually what you were aiming for? In my opinion... that process is > awful! We are better off just having a link to open the site in a new window > to buy the products, which has a multitude of it's own downsides. I obviously cannot design your product or flow for you. I'm just providing you guidance on what is available in Safari and the Storage Access API is one option you have. How you make use of it is up to you. Third parties have *never* been able to set cookies in Safari without first becoming first parties. This has been the default cookie policy in Safari since 2003. > I think you're in danger of making the mistakes of the EU Cookie Law. > Enforcing websites to have a clear cookie policy and a way to configure them > is not a bad idea, just like these privacy features are not a bad idea... > but having a pop-up on every... single... website (That nobody even reads) > turned a good idea into a terrible one! > > I'm sure this privacy stuff is your top priority, but please don't forget > about the user experience. > > As one final question... how long does the storage acceptance continue for > (as in the dialog Allow/Deny)? Once it's accepted, I can't get the dialog to > appear again. Is there also any way to manually clear it as we do with > cookies, etc? The storage access is per frame. When the requesting iframe goes away, so does its storage access. In the process of standardizing the Storage Access API, we've agreed to expand this to per-page storage access which means that access goes away when the top page navigates. Remembering the user's choice in the prompt is potentially for the lifetime of the device. If ITP decides to delete the domain's website data after 30 days of Safari use with no interaction and no successful use of the Storage Access API, the choice is forgotten too. If that never happens because the user keeps re-engaging, the choice is remembered. In addition, if the user manually deletes browsing history, the choice is also forgotten.
Even the link to the chromium article here- https://blog.chromium.org/2020/01/building-more-private-web-path-towards.html That was linked in the announcement here- https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/ States this- Some browsers have reacted to these concerns by blocking third-party cookies, but we believe this has unintended consequences that can negatively impact both users and the web ecosystem. This seems to be describing the block all 3rd party approach. Later in the same article it states this- As we previously announced, Chrome will limit insecure cross-site tracking starting in February, by treating cookies that don’t include a SameSite label as first-party only, and require cookies labeled for third-party use to be accessed over HTTPS. This will make third-party cookies more secure and give users more precise browser cookie controls. All existing applications that use Secure, SameSite tagged cookies (and there are a ton) will now promptly be broken. This shouldn't be the default, there should be an opt-in. Even Chrome/Chromium realized this was a bad idea. Tor and Brave are hardly in use- https://netmarketshare.com/?options=%7B%22filter%22%3A%7B%22%24and%22%3A%5B%7B%22deviceType%22%3A%7B%22%24in%22%3A%5B%22Desktop%2Flaptop%22%5D%7D%7D%5D%7D%2C%22dateLabel%22%3A%22Trend%22%2C%22attributes%22%3A%22share%22%2C%22group%22%3A%22browser%22%2C%22sort%22%3A%7B%22share%22%3A-1%7D%2C%22id%22%3A%22browsersDesktop%22%2C%22dateInterval%22%3A%22Monthly%22%2C%22dateStart%22%3A%222019-05%22%2C%22dateEnd%22%3A%222020-04%22%2C%22segments%22%3A%22-1000%22%7D
Men (In reply to Westley from comment #26) > Even the link to the chromium article here- > https://blog.chromium.org/2020/01/building-more-private-web-path-towards.html > > That was linked in the announcement here- > https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/ > > States this- > Some browsers have reacted to these concerns by blocking third-party > cookies, but we believe this has unintended consequences that can negatively > impact both users and the web ecosystem. The link to Chrome’s statement was about their intention to block all third-party cookies by default by 2022. Their motivations, claims, incentives, and plans beyond that have nothing to do with our changes and how we protect users. If you want to know WebKit’s position, please read our tracking prevention policy: https://webkit.org/tracking-prevention-policy/ > This seems to be describing the block all 3rd party approach. > Later in the same article it states this- > As we previously announced, Chrome will limit insecure cross-site tracking > starting in February, by treating cookies that don’t include a SameSite > label as first-party only, and require cookies labeled for third-party use > to be accessed over HTTPS. This will make third-party cookies more secure > and give users more precise browser cookie controls. > > All existing applications that use Secure, SameSite tagged cookies (and > there are a ton) will now promptly be broken. This shouldn't be the default, > there should be an opt-in. Even Chrome/Chromium realized this was a bad > idea. Tor and Brave are hardly in use- > https://netmarketshare.com/ > ?options=%7B%22filter%22%3A%7B%22%24and%22%3A%5B%7B%22deviceType%22%3A%7B%22% > 24in%22%3A%5B%22Desktop%2Flaptop%22%5D%7D%7D%5D%7D%2C%22dateLabel%22%3A%22Tre > nd%22%2C%22attributes%22%3A%22share%22%2C%22group%22%3A%22browser%22%2C%22sor > t%22%3A%7B%22share%22%3A- > 1%7D%2C%22id%22%3A%22browsersDesktop%22%2C%22dateInterval%22%3A%22Monthly%22% > 2C%22dateStart%22%3A%222019-05%22%2C%22dateEnd%22%3A%222020- > 04%22%2C%22segments%22%3A%22-1000%22%7D