NEW247565
SessionStorage set in same-site, cross-origin iframe not accessible from top frame
https://bugs.webkit.org/show_bug.cgi?id=247565
Summary SessionStorage set in same-site, cross-origin iframe not accessible from top ...
Roberto C.
Reported 2022-11-07 03:51:21 PST
Our application is hosted on subdomain.example.it. Customers can login in our application directly from a login page hosted on our subdomain.example.it, but they mainly login from a login widget contained in an iFrame inside main corporate site hosted on the main domain example.it. 1) The login widget hosted in the iFrame contained in corporate site example.it calls login API that returns an authorization token, that is set in sessionStorage in the frame context on subdomain.example.it (es: "sessionStorage.setItem("authToken", "xyz")"). 2) Then, the login widget redirect the top window to subdomain.example.it (es: "window.top.location.replace(document.location.origin)", location.origin is subdomain.example.it in the frame context) 3) The client side application so reloads on top window context subdomain.example.it, and read the authorization token to call authenticated APIs from the sessionStorage previously set (es: "sessionStorage.getItem("authToken")"). From Safari 16.1 this doesn't work anymore, because at point 3) the sessionStorage is empty, despite it was set from the same domain and the application reloads on the same tab. We confirm that this bug was introduced with Safari 16.1, it works fine in all Safari versions until 16.0.x. This bug is present in Safari 16.1 for iOS (tested on differents iPhone devices) and Safari 16.1 for macOs (tested on macOS Monterey 12.6.1). It works obiousvly an all other browsers. Can you fix it?
Attachments
Radar WebKit Bug Importer
Comment 1 2022-11-08 19:45:53 PST
John Wilander
Comment 2 2022-11-08 20:28:44 PST
Thanks for filing! We will have a look.
Sihui Liu
Comment 3 2022-11-10 17:05:05 PST
Hi Roberto, I believe this is caused by our SessionStorage partitioning(https://bugs.webkit.org/show_bug.cgi?id=210776). I am wondering if your app is broken by the partitioning (which most browsers does), or partitioning by top-level origin (which probably only WebKit does now). Does your app work correctly in recent Firefox or Chrome incognito mode?
Roberto C.
Comment 4 2022-11-11 02:52:35 PST
Hi, thanks for you reply. Our app works fine on all major recent browsers except Safari 16.1. Tested on: - Chrome (standard and incognito mode) 107.0.5304.107 - Edge (standard and incognito mode) 107.0.1418.42 - Firefox (standard and incognito mode) 106.0.5
webkit-bugzilla.mailcourier
Comment 5 2022-11-16 15:25:37 PST
Hello, I can confirm that this issue exists and that it was introduced in Safari 16.1 and still exists in Safari Technical Preview 16.4. Although for me, it appears in the opposite "direction" of Roberto, i.e. I set a sessionStorage entry in a first-party, top-level context first which is later not accessible in an iframe context anymore. But I guess the direction, whether data is set first in a top-level context or iframe, does eventually not matter. The issue seems to be, as you pointed out, that the sessionStorage is partitioned. I set up a demo here with which you can run the experiment in both directions (although the instructions are tailored to my top-level first use-case). Additionally, the demo includes experiments for testing whether service workers' shared storage is also partitioned (unfortunately, it is) and whether the user can show intent of allowing access to the partitioned data via the StorageAccessApi or installing the website to the home screen (but with both measures, the issue still exists). The demo consists of two pages on different origins: - https://debug-storage-access-main.netlify.app: the main page that requires data to be stored in the sessionStorage and be accessible regardless of being a top-level window or iframe. - https://debug-storage-access-wrapper.netlify.app: a wrapper page that embeds the main page as iframe. The demo prints messages to the console, so please keep the dev tools open for using this demo. The source code of these pages can also easily be inspected in the Safari dev tools. Honestly, I think blindly partitioning the sessionStorage without any safety-net to request access to the data under certain circumstances or with user consent, is not a good idea. I believe this is a serious change which potentially affects many web applications and was not even mentioned in the Safari changelog or the Webkit privacy blog. The handling of sessionStorage should be more in line with the handling of cookies, because the privacy-preserving handling of cookies in Safari has matured over many years now and restricting the access to sessionStorage more than the access to cookies doesn't make any sense, because then simply cookies can be used to circumvent the sessionStorage restrictions. In particular, I propose the following changes, which I believe is how cookies work in Safari: - If the Storage Access Api reports `true` for `hasStorageAccess()`, either because the user has been asked and allowed storage access, or because the Storage Access Api's heuristic decides that access can be granted without asking the user, then full access to the sessionStorage should be given. - Additional exceptions should be granted, in line with Safari's cookie handling, even if the Storage Access Api itself would not allow access. I believe for example, that Intelligent Tracking Prevention grants cookie access to eTLD+1 iframes? Maybe at least read-access can be given in the iframe under some circumstances. For my app , I'll have to switch to using cookies instead of sessionStorage in Safari for now. But note that using cookies is generally not a good replacement for the sessionStorage because they are sent to the server. In my case, the data I need in my iframe is a sensitive client-side private key, that's not meant to be leaked to the server. I'll have to implement a ServiceWorker that tries to strip the cookies, without guarantees that there might not be ever some requests that go through with the cookie, for example if the user disables Javascript. For that reason, on top I have to encrypt the private key and pass the decryption key through the url fragment (which is not sent to the server) when redirecting to the wrapper page which will then need to forward the decryption key to the iframe. All that is a lot of unnecessary extra effort only for Safari. Please don't let Safari become the next Internet Explorer.
John Wilander
Comment 6 2022-11-16 16:03:23 PST
Hi! Referring to a browser as the new Internet Explorer very rarely gets you any traction. I would encourage you to focus on the issue at hand and possible solutions. I'm the inventor of the Storage Access API and was co-editor on the spec up until recently when I handed over to Anne on our team. One of the first issues we raised in the Privacy CG repo was which storage types should be covered by the API besides cookies. It was issue #4: https://github.com/privacycg/storage-access/issues/4 That issue has been discussed and tested in browsers for a couple of years. The conclusion across implementors was ultimately to partition everything but cookies permanently and only switch cookies between partitioned and unpartitioned state through the Storage Access API. The two main reasons are Service Workers and stateful Indexed DB connections IIRC. There is no way to switch partitioning state for those two cases with a predictable, workable model for developers. The fact that SessionStorage was only partitioned recently in WebKit was only because of its per-tab, ephemeral scope. It was never intended to be accessible across sites in WebKit. The thing we'd be open to discussing is whether to partition per origin or per site. That is being discussed across browsers in this work item: https://github.com/privacycg/storage-partitioning. The challenge for us is to change per-origin partitioning which has been shipping for almost ten years for LocalStorage.
webkit-bugzilla.mailcourier
Comment 7 2022-11-16 19:10:43 PST
Hello John, thanks for your quick reply. Well, I didn't say that Safari is the new Internet Explorer, but that it shouldn't become it ;) Ok, so if I understand this correctly, Safari considers the current behavior as desirable and not as regression? And the open question is just whether the sessionStorage should be partitioned per top-level origin or top-level site? And in this context a site is defined as origin, minus the port, if I got that right? Thus, from the demo, https://debug-storage-access-main.netlify.app and https://debug-storage-access-wrapper.netlify.app would be separate sites and the sessionStorage should remain partitioned if https://debug-storage-access-main.netlify.app is embedded as iframe into https://debug-storage-access-wrapper.netlify.app? And the gist of the discussions of the implementors is that something like the Storage Access Api is not possible for sessionStorage due to challenges resulting from the transition between partitioned and non-partitioned state? Can there be other heuristics for when storage might not have to be partitioned (maybe also only granting read-access), for example if a website is installed to the home screen?
John Wilander
Comment 8 2022-11-16 19:48:54 PST
*Any* reference to a browser becoming the new IE makes browser people less likely to engage and only serves to throw shade. Unless that’s your goal, I propose you avoid it. Partitioned SessionStorage is not a regression, no. It’s a privacy enhancement in line with our official tracking prevention policy. Site is defined as registrable domain or eTLD+1. The browser community is moving towards schemeful sites which would be scheme+registrable domain. WebKit’s cache partitioning is per site but our storage partitioning is per origin. Both cases are double keyed – main frame and sub frame. The other browsers are catching up and it looks like site will be the agreed upon partitioning key. Still unclear if it’ll be schemeful and triple or double-keyed. In your case, would site-based partitioning work? Schemeful site?
webkit-bugzilla.mailcourier
Comment 9 2022-11-16 21:31:27 PST
Let's forge the IE part then ;) All I want is to hopefully help a little bit with the demo and provision of my use case. In my case, both the wrapper page and the main page, which is displayed as top level first and then as iframe within the wrapper page, live on different subdomains on the same eTLD+1. I would need some kind of storage which is accessible for the main page in the first-party context as well as the iframe context. The wrapper page doesn't need access to the storage. In the iframe, I only need read-access. Which storage technology to use doesn't matter too much, just cookies are less favorable because I need to store a client-side secret and with cookies I have to take extra care to not leak it to the server, e.g. by encrypting it and adding a cookie-stripping service worker as outlined in my previous message. My demo resembles my requirements, apart from the client-side secret encyption and cookie stripping. Both https://debug-storage-access-main.netlify.app and https://debug-storage-access-wrapper.netlify.app live on different subdomains on the same schemeful site https://netlify.app. I would need access to the same storage for https://debug-storage-access-main.netlify.app as first-party and as iframe. https://debug-storage-access-wrapper.netlify.app doesn't need any access to the storage. According to your explanations, in the iframe case the storage would be identified by the double key consisting of parent site https://netlify.app and origin https://debug-storage-access-main.netlify.app, and in the first-party case the storage would be identified by the double key consisting of the main frame site https://netlify.app and the origin https://debug-storage-access-main.netlify.app, too. Thus, the storage would in fact be shared between iframe and top-level when basing the main frame key on the site (schemeful or not) instead of the origin, which would be exactly what I need. If I got this right at least. However, that's not how it's currently behaving. I guess, because as you're saying the main frame's part of the double key is the origin and not the (schemeful or not) site? If that's the case, then switching the main frame key from origin to site would help my case. Now you're also saying that cache partitioning is already based on the site instead of the origin. But I guess that does not apply to cache storage, because that is not accessible in my demo either?
John Wilander
Comment 10 2022-11-17 07:32:14 PST
Thanks for the additional details. We’ll discuss schemeful site vs origin as partition key. The three main reasons to stay with origin are 1) origin is the security boundary the web typically uses and browsers want to move in that direction, 2) our origin-based partitioning for LocalStorage has been shipping for almost ten years and is doing fine, and 3) using site puts more pressure on the Public Suffix List which we don’t want (it’s already a problem). The main reasons to switch to schemeful site as partition key are 1) alignment with other browsers, and 2) regrettable issues caused by our recent partitioning of SessionStorage. It is unlikely that you’ll see a quick turnaround on us changing to schemeful site as partition. The only luck we have here for SessionStorage specifically is that it’s ephemeral and so we wouldn’t have to decide what to do with existing SessionStorage in such a transition.
Roberto C.
Comment 11 2022-12-06 00:05:05 PST
Hello John, any update on this issue? The main problem, apart from the technical point of view, is the fact that there hasn't been any reporting of this change, it hasn't been anticipated before the release or traced in any changelog after the release, putting developers and users in trouble. In our scenario, users are no longer able to login in our application using Safari. This is a huge problem both for us and for our users, and for Safari too I think, since all other browser are fine, it's not a good point for Safari reputation. In fact, for now and until the problem is resolved, unfortunately we have to advise our users NOT to use Safari. We'll await any update on this thread. Thank you
John Wilander
Comment 12 2022-12-06 06:54:02 PST
(In reply to Roberto C. from comment #11) > Hello John, > any update on this issue? > > The main problem, apart from the technical point of view, is the fact that > there hasn't been any reporting of this change, it hasn't been anticipated > before the release or traced in any changelog after the release, putting > developers and users in trouble. > > In our scenario, users are no longer able to login in our application using > Safari. > This is a huge problem both for us and for our users, and for Safari too I > think, since all other browser are fine, it's not a good point for Safari > reputation. > > In fact, for now and until the problem is resolved, unfortunately we have to > advise our users NOT to use Safari. > > We'll await any update on this thread. > > Thank you WebKit has been leading the way on storage and cache partitioning since 2013. Privacy protections are something we have a great reputation in. It would be helpful to understand the size of this issue and what the timeline would look like for you to switch to another solution for your session-based storage.
webkit-bugzilla.mailcourier
Comment 13 2022-12-15 09:39:44 PST
Hello John, while improving the user's privacy is honorable and might have been the reason for introducing this change, I believe site-based partitioning instead of origin-based partitioning would give the same privacy benefits (especially because stricter restrictions can be circumvented by using cookies instead) while being much less of a breaking change to the web. Regarding the size of the issue, anecdotally on the example of our project: Safari and iOS users on 16.1. were not able to log-in into our service for more than a month, until the bug was identified, different ideas for fixes tried and we eventually built a workaround for Safari. This was several days of development effort on our side for the encrypted-cookie based approach, combined with a cookie-stripping service worker. Also, Safari is quite hard to debug, if you're not a Mac and iPhone user. During that month that Safari support was broken, we recommended all users to use alternative browsers and devices. Currently, we check whether expected sessionStorage entries are missing in the iframe to try to identify whether the session storage is partitioned, and in the top level window already in advance by a user agent check. Can you help me to identify, which Webkit version first introduced this change? At the moment, we're testing the user agent for Safari or iOS >= 16.1., but better would probably be to check for the AppleWebkitKit version that introduced the change.
Roberto C.
Comment 14 2023-02-01 09:41:29 PST
Hi, any update on this? As already reported, the size of the problem is proportined on the usage of recentl versione of Safari users are no longer able to login in our application using that versions. Is there any timeline for this? I also propose the previous question again, as it could be useful for any workarounds: "Can you help me to identify, which Webkit version first introduced this change? At the moment, we're testing the user agent for Safari or iOS >= 16.1., but better would probably be to check for the AppleWebkitKit version that introduced the change."
Note You need to log in before you can comment on or make changes to this bug.