5

I've heard the discussion many times of whether storing credentials or other sensitive info in localStorage or document.cookie is more secure. But I'm currently building a platform and I was wondering, which is actually more secure for storing a session token in: localStorage or document.cookie?

The reason I ask is because by my understanding (probably wrong though):

  • LocalStorage can't be seen over HTTP requests, unlike document.cookie.
  • LocalStorage is easier to set and view data than cookies.
  • LocalStorage is much more simple (e.g. no expire times or anything like that)

But then if localStorage is so much better than document.cookie, I wonder why popular websites tend to use cookies instead.

Which one should I use and why?

2
  • These are different mechanism for different purposes and behave different from what you describe: Contrary to a cookie the LocalStorage does not get automatically send within an HTTP(S) request, but must be explicitly handled by Javascript. If the Javascript then decides to send the value over plain HTTP is up to the script, there are no inherent restrictions. Similar there can be explicit restrictions on a cookie in that in can only be send (automatically) over encrypted HTTPS. As for easier: session cookies are sent automatically whereas with localStorage it must be done explicitly. Commented Sep 26 at 13:45
  • As for security: cookies can be made not accessible by script and thus by XSS, whereas localStorage must be accessed by script and thus can be read by XSS. Cookie expiration is also a) optional (i.e. not a burden) and b) can be useful as a security feature. Commented Sep 26 at 13:49

1 Answer 1

13

localStorage isn't more secure than cookies. It has a few benefits and a lot of major downsides, not just security-related.

The benefits of localStorage compared to cookies:

  • It's inherently immune to Cross-Site Request Forgery, because tokens stored in localStorage are never automatically included in requests.
  • It's strictly bound to the document's origin, so there's no risk of accidentally leaking it to subdomains or over plaintext HTTP.

As to the downsides:

  • It obviously requires the user to have JavaScript enabled. Cookies do not have this restriction. So unless the web application already makes JavaScript support mandatory, cookies are better supported.
  • JavaScript has unrestricted access to the localStorage content. In contrast, cookies can be blocked from JavaScript with the HttpOnly flag, making them immune to exfiltration by Cross-Site Scripting.
  • The expiration time is undefined. You claim this is a benefit, but authentication tokens are supposed to expire. You do not want the token to sit in browser storage forever, especially when the device may be shared. Note that you can and should implement server-side token expiration regardless of whether the browser storage expires, but it's best to have both.
  • You do not benefit from cookie-specific security features like App-Bound Encryption in Chromium.

Besides this, cookies security has improved a lot thanks to, for example, cookie prefixes, the SameSite attribute and HttpOnly. Note that restricting a cookie to the same site (i.e., SameSite=Strict) is still more permissive than localStorage which is restricted to the same origin, so you should employ additional anti-CSRF measures like the Synchronizer Token Pattern.

5
  • Nice detailed explanation. I'll definitely be using cookies for login info from now on rather than localstorage. Thanks! Commented Sep 26 at 17:22
  • 1
    I was wondering about the at rest encryption... I wonder why they didn't use the new app-bound encryption for local storage as well? I guess they're assuming that tokens won't ever be stored there? (not a good assumption, as I've seen many people using it for tokens in SPAs) For expiration time of local storage, often the expiration can be inside the claims... the front end can then update or delete it (once the backend validates and responds...) Commented Sep 26 at 18:48
  • 2
    I'd argue that cookie expiration is mostly useless for security reasons. Tokens need to expire or be invalidated on the server, either due to a DB update or due to a signed token's self-defined lifetime being checked against the server time. Indeed, most so-called session cookies are effectively non-expiring now, as every major browser has offered session resumption for years. Otherwise, good post, though I'd argue that the CSRF risk is a little understated; samesite is less protective than it should be, especially with subdomains, so if using cookies I recommend another anti-CSRF too. Commented Sep 26 at 22:51
  • Tokens should absolutely have a server-enforced expiration time, but for the sake of defense-in-depth, they should also be invalidated by the client after some time. So I wasn't arguing for client-side expiration instead of server-side checks but a combination of both. Commented Sep 27 at 0:28
  • I've edited the answer to make this more clear and point out that even SameSite=Strict cookies need anti-CSRF measures. Commented Sep 27 at 0:29

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.