Cross-Domain LocalStorage

As you may know, LocalStorage is domain based. You can’t read or write from localstorage that’s on different domain, even if that’s subdomain. But there is iframe trick that you can use to store data from domain to it’s subdomain.

Basically to have Cross-Domain LocalStorage, you create an iframe that’s hosted on your other domain, then you send PostMessage to that iframe and inside iframe you set that value of localStorage.
Here is the code:

iFrame

window.onmessage = function(e) {
  if (e.origin !== "http://example.com") {
    return;
  }
  var payload = JSON.parse(e.data);
  localStorage.setItem(payload.key, JSON.stringify(payload.data));
};

main file

window.onload = function() {
    var win = document.getElementsByTagName('iframe')[0].contentWindow;
    var obj = {
       name: "Jack"
    };
    win.postMessage(JSON.stringify({key: 'storage', data: obj}), "*");
};

<a href="http://other.example.com/iframe.html">http://other.example.com/iframe.html</a>

If you want to save and load value from LocalStorage, you can PostMessage with method key that will indicate what action it need to take. You can also send message back from iframe to it’s parent with data read from localStorage.

iframe

document.domain = "example.com";
window.onmessage = function(e) {
    if (e.origin !== "http://example.com") {
        return;
    }
    var payload = JSON.parse(e.data);
    switch(payload.method) {
        case 'set':
            localStorage.setItem(payload.key, JSON.stringify(payload.data));
            break;
        case 'get':
            var parent = window.parent;
            var data = localStorage.getItem(payload.key);
            parent.postMessage(data, "*");
            break;
        case 'remove':
            localStorage.removeItem(payload.key);
            break;
    }
};

Your main page on example.com

window.onload = function() {
    var iframe = document.getElementsByTagName('iframe')[0];
    var win;
    // some browser (don't remember which one) throw exception when you try to access
    // contentWindow for the first time, it work when you do that second time
    try {
        win = iframe.contentWindow;
    } catch(e) {
        win = iframe.contentWindow;
    }
    var obj = {
       name: "Jack"
    };
    // save obj in subdomain localStorage
    win.postMessage(JSON.stringify({key: 'storage', method: "set", data: obj}), "*");
    window.onmessage = function(e) {
        if (e.origin != "http://other.example.com") {
            return;
        }
        // this will log "Jack"
        console.log(JSON.parse(e.data).name);
    };
    // load previously saved data
    win.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*");
};

Here is a demo that use my sysend library to send messages to other tab in same browser (the library use localStorage for this). It use iframe proxy to send message from jcubic.pl to terminal.jcubic.pl and vice versa. Iframe is hosted on both domains. (everything is done by the library, you only need to include the file from repo on other.example.com domain and call sysend.proxy('http://other.example.com')).

The only caveat is that in Firefox, it seems that you need to enable CORS on Iframe. If you use apache server you can enable it in .htaccess file with this code:

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods: "GET"

it will enable CORS for all files, if you want to enable CORS for a single file, this should work:

<Files "iframe.html">
  Header set Access-Control-Allow-Origin "*"
  Header set Access-Control-Allow-Methods: "GET"
</Files>

And that’s it you now can have Cross-Domain LocalStorage.

Published by

jcubic

I'm graphic designer and programmer from Poland.

18 thoughts on “Cross-Domain LocalStorage”

  1. Hi Jakub: thanks for the tutorial… it’s not very clear how the iframes should be set up. You have two code snippets labeled “iframe”. Are you using two iframes or just one?

  2. This is by far the best and most useful tutorial I’ve seen regarding HTML5 local storage usage. Thank you so much for sharing this knowledge with us!

  3. This isn’t that clear to be honest. You need to identify which is you parent and which is your sub-domain

    1. You don’t you can host iframe on both domains, on domain A you include iframe from domain B and on domain B you include iframe from domain A. That way you can have two directional connection, you send data from A to B and from B to A.

      If you have one iframe you always send message from host page to domain inside iframe.

  4. I’m setting localstorage from a webpage, and then trying to access the same from an iframe but it shows me null. Iframe and parent window are not from the same domain. Is there any cross domain solution for this?

    1. You need to save data to localStorage inside iframe that’s on sub domain. That’s the only way to have cross-domain localStorage, you simlpy send message to the iframe to save data.

  5. hey,
    this seems great but in this case sub domain url is limited to just one. What if i have dynamic sub domains. How can i set dynamic sub domain url inside main file’s iframe’s src.

  6. On note – meanwhile this is a smart trick to set the cross-domain local storage between domain-subdomain, keep in mind that due to the security policy on iOS devices the local storage will be associated to the compound of (host site, iframe site). It means that when you open on iOS the iframe content (domain.com), the local storage will be empty for it – but when you open it within an iframe like you set it, the local storage will be there.

      1. If you realy need to make it work on iOS, you can use webscokets or firebase (that also use websockets) on both domain and subdomation and send data that way. But if you use websockets/firebase you will not need to use iframe anymore even for non iOS.

    1. Not sure if I’ve understood correctly but you should not store login tokens in Firebase since AFAIK you make db public (or part of it) to make it work from browser, I’m not sure if you can store token that can be accessed only by single user.

      Firebase can be used to have cross-domain storage, or if you want cross-domain events, just create item and delete it immediately.

      For login you should use Firebase auth. Not sure how this will work if you want to authenticate Cross-Domain.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s