56

I am currently working on an Application which is a single page application built with Angular. It is served over HTTPS, using HSTS.

For authentication, we are using Auth0. The Auth0 documentation recommends storing the access token in localstorage.

An interceptor is then used to add this to the header of each HTTP request.

However, this answer recommends not storing any sensitive information with localstorage.

The answer is from 2011, and the author also co-wrote the OWASP HTML5 cheat sheet, which states:

Pay extra attention to “localStorage.getItem” and “setItem” calls implemented in HTML5 page. It helps in detecting when developers build solutions that put sensitive information in local storage, which is a bad practice.

I am wondering if the situation in 2017/2018 has changed. Am I OK to follow Auth0's guidelines, or should I take another approach?

Anders
  • 64,406
  • 24
  • 178
  • 215
JMK
  • 2,436
  • 7
  • 27
  • 38
  • It seems Auth0 [no longer recommends storing tokens in localStorage](https://auth0.com/docs/security/store-tokens#don-t-store-tokens-in-local-storage). – Sjoerd Jul 31 '19 at 13:50
  • Note that their own library still has a getter to retrieve the token from localStorage: https://github.com/auth0/angular2-jwt#tokengetter-function – GG. Apr 30 '20 at 18:55

4 Answers4

53

Personally I see no issue with using local storage as long as you are happy with the user not having to re-authenticate between sessions. The linked answer provides the following argument against this. I would argue it is very weak -

Underlying storage mechanism may vary from one user agent to the next. In other words, any authentication your application requires can be bypassed by a user with local privileges to the machine on which the data is stored. Therefore, it's recommended not to store any sensitive information in local storage.

This applies with any kind of authentication token. Someone local with admin privileges (assuming its not encrypted with a key tied to the users credentials) can read it out of any kind of storage, RAM or maybe even straight off of the network.

He also suggests -

(or XSS flaw in the website)

Again - this applies to any kind of token that the JavaScript can access.

Hector
  • 10,893
  • 3
  • 41
  • 44
  • 24
    +1 Is this a fair summary? "It's fine as long as you realize that you're really authenticating _the device_, not _the user_. For something stronger you may need something like TLS client authentication." – Mike Ounsworth Dec 19 '17 at 14:26
  • 4
    @MikeOunsworth I guess even that only authenticates the device with the certificate, not the user. (Unless the certificate asks for a passphrase every time) – Bergi Dec 19 '17 at 18:42
  • 5
    @Bergi Yeah, for example, certs stored in Windows CAPI are pretty well isolated between user accounts. As would be certs on hardware USB tokens or smart cards. – Mike Ounsworth Dec 19 '17 at 18:45
15

The reason local storage is considered unsafe is because any JavaScript that executes in the context of the page can access this. This opens you up to session hijacking via reflective XSS and stored XSS vulnerabilities, potentially information disclosure depending on the contents of your token.

For example: If a user goes to a page with shared content amongst other users and there is a stored XSS vulnerability another user can inject an attack that will steal your token from localstorage.

Short expiry only protects your token from replay attacks- but if a XSS vulnerability exists with access to localstorage this is going to have no affect on an active sessions as you can write a polling mechanism to extract the token from localstorage again on expiry

I suggest that you use a cookie as storage for your token.

  • Cookies can be marked as HTTP only. This will prevent JavaScript from being able to access the cookie
  • On the server have your code extract the token from the cookie and then validate it
  • Also mark it for as Secure for HTTPS only

Sorry not enough points to respond so dropping this here:

Another consideration, what is your threat model? External attackers on the web: Store the token in a cookie process at the server Users on the same machine (Non admin): Maybe session storage so no persistance Local admin: Well nothing - they are local admin, they own the system

Client certification is not really a viable authentication piece for web applications as a user - MFA authenticators are the better alternative

McMatty
  • 3,192
  • 1
  • 7
  • 16
  • Thanks very much for answering, to answer your question, this is a public website which any member of the public can register with and login to. MFA definitely on the roadmap, but tricky to implement,, not technically, but from a UX perspective as the average user is 45+. – JMK Dec 20 '17 at 22:05
  • 3
    I see this answer everywhere I look and I find it unsatisfactory. "Don't store in localStorage because it's vulnerable if an attacker has an XSS exploit." If an attacker has an XSS exploit, then it's too late anyway. It doesn't matter if they can read the sensitive information in localStorage because they can just send requests from the compromised browser directly or do anything else they wish. – TW80000 Sep 18 '19 at 16:03
  • Also, it seems like Chrome extensions can read HttpOnly cookies. What are we trying to protect against ? malicious JS on other sites ? A malicious extension ? Both ? This is a good point to consider the threat model. – Cyril Duchon-Doris Apr 10 '20 at 16:25
  • @TW80000 Your arguments are no more satisfactory than one you claims. What you're saying is basically: "Hey, a fire started in building, let's leave all doors open, because you know it's too late" – Andre Figueiredo May 27 '21 at 22:30
3

Following the advices from the auth0 blog you can counter security concerns by keeping a low token expiration value and more importantly you can encrypt the token.

An alternative approach would be the use of JSON Web Tokens in association with OAuth2.

Anders
  • 64,406
  • 24
  • 178
  • 215
Stefan
  • 131
  • 2
2

I'm not 100% into security. I read something else out of it.

The problem with "sensitive token information" is the same problem, be it a cookie or localStorage.

But you can save far more data into local storage, which might bring up the idea, that it is a good idea to store all banking information, all transfers, etc. (please insert other risky information hear. medical, judical, ...) into local storage, so you can access it offline.

The security risk of a cookie or a session is mitigated by a session timeout on server side. But local storage doesn't have a timeout. So if you store anything in the local storage be prepared, that it stays there forever. If you don't want everybody who has access to the machine to be able to read it - make sure to delete it and ensure your mechanism works under "every circumstance" (whatever this means in local storage context - imho this is not possible. But I'm a php developer, please correct me.)

  • 3
    `localStorage` does not have strong guarantees about the longevity of information (despite what the documentation says): it varies by implementation. See [here](https://stackoverflow.com/a/37105645/3757232) for some details. Still, for security purposes, it can pay to be pessimistic. – Jared Smith Dec 20 '17 at 14:02