39

Could I securely use local storage instead of cookies to store session credentials?

Would I need to store an encrypted hash??

EDIT: Would this be secure enough?

  • User logs in.

  • Server returns success message including salted bcrypt hash mixing userid, password, timestamp, and possibly ip address. This is saved in local storage.

  • On future connects this hash is sent, server assumes accountability as long as IP address hasn't changed, and time limit hasn't expired.

fancy
  • 48,619
  • 62
  • 153
  • 231
  • Local storage is permanent, it doesn't expire. I don't think that its a good idea to store session credentials permanently in the browser. That type of information should expire at the end of the session. – Šime Vidas Oct 22 '11 at 17:35
  • 3
    @Šime No, I specifically want it to be persistant. It's validity can expire server side. – fancy Oct 22 '11 at 18:07

4 Answers4

23

localstorage is just as vulnerable to being read by JavaScript as cookies are.

localstorage can be read using JavaScript from the same domain, if you control all the JS on the domain, then this shouldn't be a problem. But if any other code is executed (via injection for example, or if you share the domain with someone else), they will be able to access the storage data.

This is the same for cookies however, but typically the cookie is set to HTTPOnly so JavaScript cannot read it.

In either case, plain-text login information shouldn't be stored in either cookies or localstorage anyhow, as if someone does get hold of them, they can continuously make a new session for themselves.

You should encrypt an authenticated identifier (such as their user ID) along with the datetime of the session expiration, and then store this value in either a cookie or local storage. This token is then validated on each server call.

simbolo
  • 7,279
  • 6
  • 56
  • 96
  • 1
    Would storing a salted bcrypt hash of userid, password, and timestamp be secure enough that if it was present I could assume the identity of the user? Then I can just decide server side how long this assumption should last? – fancy Oct 22 '11 at 14:51
  • 1
    Yes, I use bcrypt but I don't encrypt the userid/password. To issue the token to begin with, the password is matched, then only the userID is stored, along with the salt. So long as you also include a timestamp this is fine too, for expiration as necessary. On the server I detect the presence of this token, that I can decrypt it, that the userId contained within exists, and the timestamp has not expired, only after all this do I assume the identity of that user. – simbolo Oct 22 '11 at 18:36
  • Ah ok, you decrypt it? You don't just match it with a reference? How do you decrypt it? – fancy Oct 22 '11 at 20:04
  • Thats going beyond the scope of the initial question, you should open a new one. There are already a bunch of resources available on authentication token methods, including the use of bCrypt. But essentially it makes little difference using localStorage or cookies to store the token once it has been generated, which is the question posed. What you store can be the output of FormsAuthentication.Encrypt(), after you've populated a FormsAuthenticationTicket with your users credential information. The resulting string is an encrypted token, using whatever method you set in web.config – simbolo Oct 22 '11 at 23:21
  • (assuming your using .NET for example, not sure what backend server you're using). – simbolo Oct 22 '11 at 23:22
14

If you're going to be using local storage, why store user credentials or anything derived from them at all?

What I've been looking into doing is:

Upon successful login, generate a completely random string unrelated to user credentials and store that in the database, along with an expiry date. I would then pass that string to my js to be stored in local storage.

From then on, so long as that local storage credential matches the database one and the timeout has not expired, I automatically consider them logged in.

This way, there is no risk concerning the exposure of the user's credentials from local storage. However, with this temporary unique string essentially functioning as a sessionID, you will still to need to be aware of and take precautions against the risks associated with session hijacking.

In any case, my understanding is that local storage is as secure as the server behind your site is. By that I mean local storage is only accessible via scripts coming in through your own domain, so you're safe so long as the only front code running is your own.

David Miller
  • 189
  • 1
  • 4
  • So what about private sessions? When you don't have access to local storage? – Farshid Ashouri Jan 28 '18 at 04:16
  • 1
    @Farsheed You should not be able to continue a session in incognito mode that was started outside of it, that's kind of the point of private sessions, think of it as if you were using an entirely different browser. – David Miller Feb 19 '18 at 18:53
6

You server shall generate some token - unique (for the server) piece of data that cannot be used to discover username/password. Only that token can be stored on user's machine in any form. Neither localStorage nor cookie are secure. So the same rules applied to them in this respect.

You should have some means to expire such token otherwise once stolen such token can be used instead of real credentials.

c-smile
  • 26,734
  • 7
  • 59
  • 86
2

If you're going to use localStorage instead of cookies, you can make things more secure than cookies. That's because you don't need to send a session id to the server with each request, making it a bearer token. Instead, you can store a user secret on the client side in localStorage, and use it to sign your requests in addition to the corresponding public key being sent down and used as the session id. This way, no one on the server side or proxy can fake your requests.

Gregory Magarshak
  • 1,883
  • 2
  • 25
  • 35