cross domain localstorage with javascript
Asked Answered
S

5

55

We have a javascript api.js which is hosted on domain api.abc.com. It manages the local storage.

We included this javascript in our websites at abc.com and login.abc.com as a cross domain js like

<script src="http://api.abc.com/api.js">

I understand that localstoarge is per domain basis. However since api.js is loaded from api.abc.com, I expected that it will have access to local storage of api.abc.com from both the domains. Unfortunately, it doesn't seem to be the case. When api.js stores a value in localstoarge from one domain, it's not accessible to it when loaded from other domain.

Any idea?

Sandry answered 27/11, 2015 at 12:30 Comment(4)
I don't think so. The api.js is executed on a client side of the browser, with the domain. That's what matters.Fanni
It doesn't matter from where the script came from (the script can be loaded from CND you don't expect localStorage to be saved on CDN domain), but if you need cross-domain localStorage there is a way using proxy iframe, check this article Cross-Domain LocalStorage. You can use iframe to interact with any API on different domain.Abb
Does this answer your question? use localStorage across subdomainsDinny
To pass localStorage values across domains via a link, I would pass them as search parameters in a query string.Margaretmargareta
B
22

How about using cross domain postmessage and iframes?

So on your wrong-domain-page you include an iframe that posts messages with the cookie data back.

Here is a solid example of cross domain postmessages: http://blog.teamtreehouse.com/cross-domain-messaging-with-postmessage

live example: http://codepen.io/anon/pen/EVBGyz //forked sender code with a tiiiiiny change :) :

window.onload = function() {
    // Get the window displayed in the iframe.
    var receiver = document.getElementById('receiver').contentWindow;

    // Get a reference to the 'Send Message' button.
    var btn = document.getElementById('send');

    // A function to handle sending messages.
    function sendMessage(e) {
        // Prevent any default browser behaviour.
        e.preventDefault();

        // Send a message with the text 'Hello Treehouse!' to the new window.
        receiver.postMessage('cookie data!', 'http://wrong-domain.com');
    }

    // Add an event listener that will execute the sendMessage() function
    // when the send button is clicked.
    btn.addEventListener('click', sendMessage);
}

Receiver code:

window.onload=function(){
    var messageEle=document.getElementById('message');
    function receiveMessage(e){
        if(e.origin!=="http://correct-domain.com")
        return;
        messageEle.innerHTML="Message Received: "+e.data;
    }
    window.addEventListener('message',receiveMessage);
}
Bandoleer answered 27/11, 2015 at 13:0 Comment(2)
The live example no longer works, since one of the links is broken.Margaretmargareta
Shouldn't "correct-domain.com" be also in the "postMessage"?Cup
S
10

As noticed in your post the localStorage (sessionStorage too) won't be stored on the storage related to the domain api.abc.com. If this was the case, by using CDN version of a library using localStorage you would have to share storage with all the other websites using this library.

One good solution could be to use an iframe with postMessage as explained in the following stack overflow: use localStorage across subdomains

Segment answered 27/11, 2015 at 13:6 Comment(1)
True, your point is taken however CDN is often different domain and I wish it was allowed between subdomains just like cookies are allowed.Sandry
P
5

You might try this cross-storage from Zendesk. Basically, There are hubs and clients:

  • hubs: reside on any server, interact directly with LocalStorage API

  • clients: load the hub using an embedded iframe, and post messages, interact with data

Key things is you can configure the permission (get, set, delete) that each host or domain client could have. The library is divided into two types of components: hubs and clients.

Care should be made to limit the origins of the bidirectional communication. As such, when initializing the hub, an array of permissions objects is passed. Any messages from clients whose origin does not match the pattern are ignored, as well as those not within the allowed set of methods. The set of permissions are enforced thanks to the same-origin policy. However, keep in mind that any user has full control of their local storage data - it's still client data. This only restricts access on a per-domain or web app level.

Preston answered 30/9, 2016 at 9:56 Comment(1)
Unfortunately "cross-storage from Zendesk" hasn't been updated in 6 years :-(.Pulmotor
T
4

The other answers all ignore the fact that you're not really operating cross-domain, just between subdomains.

You still need a hidden iframe to encapsulate the origin of the localStorage store you want to access (api.abc.com), but by setting document.domain = "abc.com" on both main window and hidden iframe, they can interact directly. (Though note that this is deprecated, may have security implications, and in Chrome at least requires also sending a Origin-Agent-Cluster: ?0 header).

Then you can literally just use hiddenIFrame.contentWindow.localStorage instead of window.localStorage, and forget about the headache of doing anything via postMessage().

I posted a more detailed version of this answer here: https://mcmap.net/q/103207/-can-html5-databases-and-localstorage-be-shared-across-subdomains

Tedric answered 26/8, 2020 at 17:13 Comment(4)
In many cases, this may not be a good idea. Imagine there is an XSS vulnerability in one domain. Then by sharing in the above way, that leaks into the other domain. Message posting is safer because it makes you think harder about what you want to share between the two domains.Tabatha
@Colm: That's true, and I've added a note mentioning it to my more detailed linked answer.Tedric
Setting document.domain is now prohibited within a cross-domain iframe in Chrome, even if it's only cross-site (developer.chrome.com/blog/immutable-document-domain).Poacher
@Abel, according to the article you linked, it's only prohibited by default, and can be re-enabled if the Origin-Agent-Cluster: ?0 header is sent.Tedric
C
3

Use iframe to store data in local storage & postMessage API to communicate between parent domain & iframe

  1. Create Iframe with message event listener to store data in local storage of iframe domain

    window.addEventListener("message", handleMessage, false);
    
    function handleMessage(e) {
    let {key, value, method} = e.data;
    if (method == 'store') {
        window.localStorage.setItem(key, value); // Store data in iframe domain local storage
    } else if (method == 'retrieve') {
        let response = window.localStorage.getItem(key);
        e.source.postMessage({
            key,
            response,
            method: 'response'
        }, '*'); // Retrieve local storage data
    }
    

    }

  2. Pass Message from parent domain to iframe to store data

    document.getElementById('myFrameId').contentWindow.postMessage({
    key: 'key',
    value: data,
    method: 'store'
    });
    
  3. Retrieve data from Iframe

     document.getElementById('myFrameId').contentWindow.postMessage({
     method: 'response',
     key: 'key'
     });
    
     window.addEventListener("message", handleResponse, false);
    
     function handleResponse(e) {
      let {key,value,method} = e.data
      if (method == 'response') {
        console.log('Response Key', key);
        console.log('Response value', value)
      }
     }  
    
Capacity answered 30/5, 2021 at 4:4 Comment(1)
I believe there's an error in step 3. method when posting the message should be retrieve, not response.Birdman

© 2022 - 2024 — McMap. All rights reserved.