We are working on two web applications that are hosted on two different subdomains of the same domain:
https://subDomainA.domain.com
https://subDomainB.domain.com
Both web applications are showing an iFrame hosted on a third subdomain:
https://subDomainC.domain.com
We are using postMessage to communicate between top window and IFrame window.
Within the iFrame shown on subDomainA, we are setting an AuthToken:
localStorage.setItem("AuthToken", "JWTAuthToken")
When we navigate to subDomainB and try to run the following code within the iFrame:
localStorage.getItem("AuthToken")
The result is null.
This only happens in the Safari browser.
All other browsers share the LocalStorage within these IFrames
We are on the same domain, i.e. the same "eTLD+1" (domain.com)
Doing the exact same thing with cookies works!. Just not with LocalStorage
Opening subDomainC directly in the browser and setting the data persists them for the IFrames as well.
Is this a indended behaviour of Safari or do we have an issue with our implementation?
This is the expected behavior in Safari. Safari's Intelligent Tracking Prevention (ITP) partitions browser storage based on the top frame. Here's how WebKit's documentation explains it:
Partitioning is a technology to allow third-parties to use storage and stateful web features, but have those isolated per first-party website. Let’s say adtech.example is a third-party under both news.example and blog.example and that adtech.example uses LocalStorage. With partitioned LocalStorage, adtech.example will get unique storage instances under news.example and blog.example which removes the possibility to do cross-site tracking through LocalStorage.
References:
https://webkit.org/tracking-prevention/#partitioned-third-party-localstorage
Iframe localStorage on Safari and Safari mobile
In slightly plainer English, https://github.com/zendesk/cross-storage says :
Notes on Safari 7+ (OSX, iOS)
All cross-domain local storage access is disabled by default with Safari 7+. This is a result of the "Block cookies and other website data" privacy setting being set to "From third parties and advertisers". Any cross-storage client code will not crash, however, it will only have access to a sandboxed, isolated local storage instance. As such, none of the data previously set by other origins will be accessible. If an option, one could fall back to using root cookies for those user agents, or requesting the data from a server-side store.
This may be of use:
https://webkit.org/blog/8124/introducing-storage-access-api/
According to the same-origin policy, different subdomains are considered cross-origin.
You should use postMessage for cross-origin communication.
It seems that the recent updates to the Safari browser (Prevent cross-site tracking) blocks any cookies from being generated when the Matomo domain doesn't match the website it's being loaded from.
This breaks the use of iFrames for Matomo that require cookies to be set (For example the logme feature)
There doesn't seem to be any way to fix this with headers (Eg using CSP or CORS configurations).
current workarounds exist that I've found:
Disable the "Prevent cross-site tracking" setting in the Privacy settings
Redirect the visitor to the page outside of an iFrame to set the cookie - after this the iFrame can load as long as the CORS configuration is correct and the browser isn't completely blocking the iFrame from loading.
I'm not sure how many users are using iFrames that would require cookies to be set, but they would be impacted if any of their users use Safari.
Related
I have a client website that is managed by client team and post clicking on login it comes to the site which is managed by us. Till now, we were extracting the referer URL from the request header and using it to take further actions, but currently due to some changes in the Chrome browser and Edge browser policy we are unable to get the complete referer URL. It works fine in Firefox and Internet Explorer. This is probably because of the browser policy which is restricting the complete referer URL to be send when sec-fetch-site is cross-site. Please help me with some easy code level ways (Java/JSP/Javascript) to extract the complete URL. I tried exploring few links but none helped me resolving this.
Mozilla Firefox and Internet Explorer use a referrer policy called ‘no-referrer-when-downgrade’. Earlier Chrome also used the same policy but it has now shifted to ‘strict-origin-when-cross-origin’ which restricts the referrer URL to only include the domain of the URL.
The resolution to make it work it for Chrome browser as well is to set the policy to ‘no-referrer-when-downgrade’ in the page where your request begins from i.e. the initial page (which in your case is the client managed one), which will help send the complete details and the browser’s default policy won’t be applied. You may refer to below link for better understanding of these changed policies:
https://www.w3.org/TR/referrer-policy/
I'm using localforage to persist the state for a react app. However, It's still not perfect. Because in safari private mode, the state will be removed after refreshing the page. What is the fallback for this situation?
The whole point of Private/Incognito/etc mode is that sites are not able to persist data beyond the browsing session, and therefore (1) leave a trace on the user's device that the site was accessed and (2) allow the site or third party content to recognize and track visitors.
If there were such a mechanism it would be considered a serious privacy bug by the browser vendor and fixed promptly.
We have a web app that runs in Facebook (i.e. a running in an iFrame at a different domain). If a Safari user has Cookies and Website Data set to the default, "Allow from websites I visit", the data we store via localStorage.setItem is acting like sessionStorage, i.e. it's not available beyond the user's current session (i.e. after the user closes the tab). If we change the setting to "Always allow", it works fine just like in Chrome, IE , etc.
As a test, we've tried navigating the browser to our app's domain (https://ourappname.appspot.com) directly and it works fine there. And also then it should truly be a visited website, but when going back to the game within Facebook, the problem still exists.
Note that the setItem call is succeeding, it's just that getItem doesn't return anything in a subsequent session. (So it's not like when the user is Private Browsing and the setItem call itself fails with a Quota Exceeded error.)
What do we need to do to support Safari so that our app, running within Facebook, can use localStorage as intended where the data will survive between sessions?
It's either a bug in Safari or a security feature.
You are visiting FaceBook and not your website. Your app is in iframe which would violate security model if it let you read any data from the browser. Think if a competitor site read data it did/didn't set. That'd constitute an information leak.
Safari is doing it's job well in that regard.
Ideally, in "Allow from websites I visit" mode, no browser should let iframes to set data to localStorage; even if every domain has their own storage-sandboxes.
What's troubling me is why are they even letting you write to localStorage from iframe at all (in your 'Allow for only sites I visit' mode)? That might actually be a bug - a information spoof attack enabling bug.
I think it's because security-exceptions were dropped from localStorage in case of not-same-party origin of request. So Safari might actually will not throw error but let it silently fail (in some cases). That's probably why your setItem call is succeeding.
At this point, with the given information, I suspect, sir you are out of luck due to Safari programmers following standard to the letter.
I'm still waiting on a reply from Apple, but it's safe to say we're stuck with this behavior. So Anubhav's answer is accurate, but we still needed a solution.
So as a work around, we created new endpoints on our server for persisting/restoring game state. We only utilize this for Safari, for all other browsers we're still persisting our game state in localStorage.
There is a slight performance penalty for the user. And a slight server cost. Not a sexy solution, but now our Facebook canvas app supports Safari.
I'm trying to use the XAuth cross domain cookie trick with iOS 7. It does not seem to work.
When I mention cookies below it's really both cookies and localStorage values being set.
I have a page on www.client1.com opening a static webpage in an iframe on www.server.com that sets a cookie with a unique id. Next I open a new window/tab that loads www.client2.com that opens an iframe to www.server.com and attempt to access that same unique id from the cookie previously set.
This works on all platforms, including previous versions of iOS, that I have tried. But not on iOS 7.
I'm using the postMessage method to send information between the iframe and main frame.
What have they changed in iOS 7? Is there any way around this?
I was having a similar problem with a child iframe on b.com with an app cache manifest, hosted in a page served from a.com. The cache manifest would never be fetched by Safari so the child app would never be cached. Happened in WebViews also.
It turns out that iOS7 has a new Privacy/Security setting for blocking cookies (in previous versions of iOS the setting was for accepting cookies), and I found it must be set to 'Never'. The default is to block cookies 'From third parties and advertisers', and that is why my cache manifest was being blocked, and why your cookies aren't being retained.
I have a specialized audience so I can direct users to change their settings. I suppose without this luxury you would have to resort to redirection-fu to flip between the domains and back to ensure that the proper cookies get dropped. However, that approach still may not let child iframes see their own cookies -- Safari may block (i.e., not send) those cookies when the iframe is hosted in a page from a different domain. I haven't tested to confirm this, however.
FYI...
I am a Product Manager who's app had an issue with the cookie updates made in iOS7.0
- We use cookies to support user authentication....and the new cookie policy applied to both Safari AND apps.
This issue appears to have been addressed in iOS 7.0.3
I am working on a site for mobile devices. The site is available through normal web browsers and also through an app which is just a browser shell and brings up the mobile site. In our efforts to speed up the loading of the site in mobile we have reduced requsts, made use of data uris, etc. Recently we have started using localStorage to save styles and JavaScript data to the device.
Why you may ask?
In our testing, mobile browsers maintain their cache throughout their session and when the browser is closed and re-opened. The app maintains its cache as long as it is being used, but when it is closed and re-opened it re-requests everything, thus slowing down that initial load.
The problem is, we have styles and JavaScript that are specific for if you are in the browser or in the app for a few small things. We've seen a few things break around these subtle differences and my best theory is that localStorage is shared between the browser and the app. And a user that uses both the site and the app may have problems if the localStorage was set by one and needs something else for the other.
I can't find any documentation that confirms this theory or not, and short of creating an app just to test this I figured I'd ask if anyone has any ideas?
If you trust Apple...
Like cookies, storage objects are a shared resource common to web
content served from the same domain. All pages from the same domain
share the same local storage object. Frames and inline frames whose
contents are from the same origin also share the same session storage
object because they descend from the same window.
Because the storage resource is shared, scripts running in multiple
page contexts can potentially modify the data stored in a storage
object that is actively being scrutinized or modified by a script
running on a different page. If your scripts do not notice these
changes, you may not get the results you expect.
If you are populating your app with data from the same place as the web app, I would suspect there are some keys being modified by the other one. I know that using sessionStorage.clear() will wipe out keys if the web app and offline app load data from the same domain.
As Chiguireitor said it depends on what mobile OS the user is using, but in my experience iOS 4 & 5 share the same localStorage whether you're accessing the mobile app through the Safari browser or as a homescreen web app. And of course if you package it with something like Phonegap it acts as its own app therefore its localStorage is not shared.