javascriptlocal-storagesame-origin-policysession-storagepostmessage

Sharing localStorage data between different domains using iframe not working


Im trying to follow this article that teaches us how to share localstorage data between domains if you have an iframe embedded.

https://www.internetkatta.com/share-cookies-or-local-storage-data-between-cross-domain

So to try it out, I created two separate projects with its own html files and index files respectively. I then launched both html files in the server using VS Code's live server. I was trying to get http://127.0.0.1:5500/getlocalstorage.html to pass in the user login data to http://127.0.0.1:5501/getlocalstorage.html, however, it returns no data in the localstorage tab and just shows as:

Is there anything I am doing wrong here? I am trying to pass in the dummy login info from localhost:5500 to localhost:5501. Please see my code below:

Localhost 5500's index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <script>
      function postCrossDomainMessage(msg) {
        var win = document.getElementById("ifr").contentWindow;
        win.postMessage(msg, "http://127.0.0.1:5500/");
      }
      var postMsg = { login: "user" }; // this is just example
      postCrossDomainMessage(postMsg);
    </script>
    <script src="index.js"></script>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <iframe
      style="display: none"
      src="http://127.0.0.1:5501/getlocalstorage.html"
      id="ifr"
    ></iframe>
    <h1>http://127.0.0.1:5500/index.html</h1>
  </body>
</html>

Localhost 5501's html file(getlocalstorage.html):

<!DOCTYPE html>
<html lang="en">
  <head>
    <script>
      var PERMITTED_DOMAIN = "http://127.0.0.1:5500";
      /**
       * Receiving message from other domain
       */
      window.addEventListener("message", function (event) {
        if (event.origin === PERMITTED_DOMAIN) {
          //var msg = JSON.parse(event.data);
          // var msgKey = Object.keys(msg)[0];
          if (event.data) {
            localStorage.setItem("localstorage", event.data);
          } else {
            localStorage.removeItem("localstorage");
          }
        }
      });
    </script>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>http://127.0.0.1:5501/getlocalstorage.html</h1>
  </body>
</html>

New Error that is being shown in console

localhost 5500 console error

Do you see anything that I might have done wrong here? Thanks!

This is in localhost 5500 tab: enter image description here

And in localhost 5501 localstorage tab:

enter image description here


Solution

  • The script tag is before the iframe tag. It is also executed before the iframe is created. Hence, searching for ifr returns null and null does not have a contentWindow, which throws an error. You will need to postpone the JS execution after the page load, like this:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <script>
          function postCrossDomainMessage(msg) {
            var win = document.getElementById("ifr").contentWindow;
            win.postMessage(msg, "http://127.0.0.1:5500/");
          }
          function load() {
              var postMsg = { login: "user" }; // this is just example
              postCrossDomainMessage(postMsg);
          }
        </script>
        <script src="index.js"></script>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
      </head>
      <body onload="load()">
        <iframe
          style="display: none"
          src="http://127.0.0.1:5501/getlocalstorage.html"
          id="ifr"
        ></iframe>
        <h1>http://127.0.0.1:5500/index.html</h1>
      </body>
    </html>
    
    

    Note that the load function is not executed in the script tag, only defined. It is the onload event defined in body that triggers it.

    EDIT

    The line of localStorage.setItem("localstorage", event.data); stores an item into localStorage with the key of 'localStorage' and the value of [Object object], because into localStorage you will store strings. So, you will need to stringify the object that you have. So, you will need to do something like

    localStorage.setItem("localstorage", JSON.stringify(event.data));

    And you can read from it via

    JSON.parse(localStorage.getItem("localStorage"))

    Example

    enter image description here