Skip to main content Accessibility Feedback

Where should you store authentication tokens?

This is an excerpt from my brand new pocket guide and video course on Token-Based Authentication. It’s part of a new Expert Bundle that also includes courses on State-Based UI and Serverless (available now!).

Yesterday, we looked at terminology around token-based authentication. Today, I want to discuss where to store authentication tokens and how to keep them safe.

Quick note: in yesterday’s article, I accidentally mixed up the terms authentication and authorization (repeatedly). The article on my site has been updated to correct this. Thanks to everyone who pointed it out!

Authentication Token Vulnerabilities

Authentication tokens can provide more security than permanent credentials like a username and password. But if a token is stolen, it can be used to access another user’s account.

There are two types of attacks that can result in stolen authentication tokens:

  • In a cross-site scripting (XSS) attack, malicious JavaScript is injected into your site and run. This code can do things like grab authentication tokens from localStorage or cookies or send them to a third-party.
  • In a cross-site request forgery (CSRF) attack, an HTTP request is sent to your site from a third-party site (often by submitting a hidden form on a malicious site). If the user is logged into your site already, their authentication cookies will be automatically sent, initiating an action on their behalf without their knowledge.

There a lot of debate about whether authentication tokens should be saved in localStorage or cookies to reduce these risks.

Where should you store authentication tokens?

Tokens stored in localStorage are automatically protected from CSRF attacks, because localStorage items are not automatically sent to servers with each HTTP request. But they are vulnerable to XSS attacks, where they can be easily accessed by JavaScript.

localStorage.setItem('token', 'abcd1234');

Cookies can be set with an httponly flag. This blocks JavaScript from accessing the cookie, protecting it from a XSS attack. It will still be automatically sent with each HTTP request, so it’s still vulnerable to CSRF attacks.

Many articles suggest that a cookie set with the httponly flag is the more secure option, because while the token can be used, it’s never exposed.

document.cookie = 'token=abcd1234; secure; httponly;';

However, JavaScript cannot be used to set a cookie with the httponly flag, either. The cookie can only be set by a server. If your app is entirely client-side, and you store your token with JavaScript, you can’t use this flag. In that case, a cookie is just as vulnerable to XSS attacks as localStorage.

So, which one should you use?

  • For client-side only apps, localStorage may actually be more secure, since it’s not vulnerable to CSRF attacks.
  • If you can get and set your token with server-side code, a cookie with the httponly flag is probably be the better choice.