Search code examples
javascriptiframesafarilocal-storage

Safari LocalStorage not shared between IFrames hosted on same domain


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?


Solution

  • 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.com is a third-party under both news.example.com and blog.example.com and that adtech.example.com uses LocalStorage. With partitioned LocalStorage, adtech.example.com will get unique storage instances under news.example.com and blog.example.com 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/


    In summary, potential solutions include:

    1. Use root-domain cookies instead.
    2. Use a server-side store, and request the data you need via JSON.
    3. If all of your domains are located on the same server, but different Docker images or something, you can Reverse-Proxy and/or Alias all of your websites so they appear as one single domain.
    4. Host your iframe you want to share on example.com (Not www!), and then share it between one.example.com and two.example.com.
    5. Use the Storage Access API.