59

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?

2

4 Answers 4

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.

8
  • 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." Commented Dec 19, 2017 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
    Commented Dec 19, 2017 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. Commented Dec 19, 2017 at 18:45
  • 1
    That's very bad advice. The actual issue is that JS should not be able to access the auth token. That way a XSS attack can only steal your users account when they are typing their credentials. This is a way smaller attack surface than being able to steal your users account simply by loading malicious JS on ANY page of the app at ANY time (the user just has to access the website while the malicious JS is in place). If the attack can only occur on the login page, your already authenticated users are safe and way less users will be affected until you detect and remove the malicious JS. Commented Dec 29, 2023 at 9:19
  • @CheddarLizzard - then the malicious JS would just log you out. Its almost universally standard practice / OAuth authorisation code and implicit flows result in the auth token (or a reference token) being exposed to JS.
    – Hector
    Commented Jul 3 at 15:27
18

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

5
  • 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
    Commented Dec 20, 2017 at 22:05
  • 4
    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
    Commented Sep 18, 2019 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. Commented Apr 10, 2020 at 16:25
  • 1
    @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" Commented May 27, 2021 at 22:30
  • @TW80000 Security is about layers, not about having a magic silver bullet. Commented Dec 29, 2023 at 9:27
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.

2
  • How would encrypting the token achieve anything? Where do you store the encryption key and how do you retrieve it if the browser is closed? Low token expiration is a security theater: these attacks are automated and happen nearly instantly. Commented Dec 29, 2023 at 9:37
  • @CheddarLizzard - You'd use the web crypto api storing the key objects in IndexedDB, although the value add is questionable.
    – Hector
    Commented Jul 3 at 15:29
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.)

1
  • 3
    localStorage does not have strong guarantees about the longevity of information (despite what the documentation says): it varies by implementation. See here for some details. Still, for security purposes, it can pay to be pessimistic. Commented Dec 20, 2017 at 14:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .