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 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.

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>
Advertisements

, , ,

  1. #1 by Mide Thesis on September 2, 2014 - 03:55

    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 by jcubic on April 25, 2015 - 15:46

      Second iframe is extension of the first one to allow to set, get and remove data from localStorage.

  2. #3 by shaq1nj on October 16, 2014 - 22:25

    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. #4 by Eric on January 16, 2015 - 13:11

    meh

  4. #5 by fgsdjhfosdjfksdl on November 20, 2015 - 06:28

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

    • #6 by jcubic on December 24, 2016 - 17:35

      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.

  5. #7 by Tushar on April 28, 2016 - 15:09

    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?

    • #8 by jcubic on June 29, 2016 - 14:21

      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.

  6. #9 by Devesh Jadon on July 21, 2016 - 08:19

    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.

  7. #10 by Konrad on November 24, 2016 - 14:31

    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.

    • #11 by GL on December 20, 2016 - 11:08

      Anyway to solve this problem on ios ?

      • #12 by jcubic on April 2, 2017 - 20:55

        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. Cross-Domain LocalStorage | Web Apps with Coffe...
  2. Cookies, Third-Party Cookies, and Local/Session Storage – hscoelho

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: