13

I would like a method of storing information on the client that can be accessed by both the SSL and nonSSL version of my site. localStorage is a great mechanism but it can only be accessed by the current protocol.

I'd like to be able to store a piece of information via javascript on the non-ssl(http) portion of my site and access it on the SSL (https) portion of my site.

Does anyone know of a good way to share stored client-side information between ssl and non-ssl pages?

I know I can always default to a cookie.. but I hate the idea of having to send the cookie back and forth for every single request.

jeremysawesome
  • 7,033
  • 5
  • 33
  • 37
  • 2
    Is there a good reason to not just SSL the entire site? It's a bit more load, but does solve the problem (and makes paranoid people happy). – zebediah49 Aug 01 '13 at 18:09
  • no kidding right? That was my first thought too, but the powers at be have deemed that there should be two separate sides of the site. I'll ask again... – jeremysawesome Aug 01 '13 at 18:13
  • 2
    Sadly, "Because Management" is a valid reason. You can try selling it on the "extra security never hurt anyone" point or whatever, but I suppose let's find a real solution. Would it be impractical to duplicate the DOM storage, and use a combination of cookie (with minimal data), AJAX, and a hash function to check if the DOM store needs to be updated? – zebediah49 Aug 01 '13 at 18:18
  • That sounds intriguing. What are you thinking? – jeremysawesome Aug 01 '13 at 18:26
  • This somewhat depends on the details of how much data you have, how frequently it changes, and how frequently users switch sides, but the basic idea is something like: 1. save data to DOM, along with its hash. 2. send hash in cookie instead of full data. 3. JS checks that cookie hash and DOM data match. 4. If DOM is determined to be out of date, use AJAX to acquire new data for DOM. – zebediah49 Aug 01 '13 at 18:30
  • See: http://stackoverflow.com/questions/5843305/switching-between-http-and-https-pages-with-secure-session-cookie -- there are a number of vulnerabilities discussed with switching, but there's some useful stuff there. – zebediah49 Aug 01 '13 at 18:35
  • 1
    @zebediah49 I ended up using your approach. It is working fantastically. Thanks for suggesting a different approach rather than answering "you can't". – jeremysawesome Aug 16 '13 at 19:54

3 Answers3

10

Compiled from the comments leading to this answer; I welcome @jeremyisawesome to edit in his final techniques:


Fist choice: Use SSL, across everything. Many users want that, and it is (with the exception of the somewhat higher resource use) a superior option in nearly every way. Also it is the trivial solution.

Sadly, "Because Management" is often a valid reason, and while you can try selling it on the "extra security never hurt anyone" point or whatever, a real solution would be preferred.

I propose the following: duplicate the DOM storage, and use a combination of cookie (with minimal data), AJAX, and a hash function to check if the DOM store needs to be updated. The exact implementation details depend on how much data you have, how frequently it changes, and how frequently users switch sides, but the basic idea is something like this:

  1. save data to DOM, along with its hash.
  2. send hash in cookie instead of full data.
  3. JS checks that cookie hash and DOM data match.
  4. If DOM is determined to be out of date, use AJAX to acquire new data for DOM, and update it asynchronously.

Switching between HTTP and HTTPS pages with secure session-cookie -- there are a number of vulnerabilities discussed with switching, but there's some useful stuff there.

Community
  • 1
  • 1
zebediah49
  • 7,467
  • 1
  • 33
  • 50
  • 2
    This is the best solution so far. I decided to use the hash method mentioned. I store a hash in the cookie and in the DOM storage. I then check that the hash in the cookie is the same as the hash in DOM storage. If they are different I request new information from the server using AJAX. This keeps both SSL and non-SSL versions of the site in sync without needing a gigantic cookie or an AJAX request every single page load. – jeremysawesome Aug 19 '13 at 14:34
8

localStorage / sessionStorage ssl / non-ssl sharing in production

The way I did this was to use an iframe that does a postMessage to its parent. The iframe is always on https but the parent can be either http or https. This solution assumes the modifications are on SSL only to the storage and syncs it back for non SSL but you could adapt this to send modifications both ways so the non ssl parent sends changes down to the ssl child.

ssl iframe source (storage-sync.html):

if (sessionStorage.cart)
  try {
    var obj = { cart: JSON.parse(sessionStorage.cart) };
    parent.postMessage(JSON.stringify(obj), 'http://yourdomain.com');
  } catch(ex) {
    console.log(ex);
  }

ssl/non ssl parent source:

window.addEventListener('message', function(ev) {
  if (ev.origin !== 'https://yourdomain.com')
    return;
  try {
    var obj = JSON.parse(ev.data);
    sessionStorage.cart = JSON.stringify(obj.cart);
    cart.reload();
  } catch(ex) {};
});

$('body').append('<iframe style="display:none" src="https://yourdomain.com/storage-sync.html?r=' + Math.random() + '"></iframe>');

Placing the target origins to the right protocols ensures you won't be sending messages to wrong ones.

King Friday
  • 25,132
  • 12
  • 90
  • 84
5

It's not technically possible as http as https schemes are deemed different origins as well as no-mix content limitations browsers has (now also in Firfox).

From the specs (Web Storage):

4.3.1 Security

User agents must throw a SecurityError exception whenever any of the members of a Storage object originally returned by the localStorage attribute are accessed by scripts whose effective script origin is not the same as the origin of the Document of the Window object on which the localStorage attribute was accessed.

So what is origin - lets look at CORS (Cross-Origin Resource Sharing) which states:

...origin is composed of [..] the scheme, hostname, and port.

And further:

https to http is not allowed.