Where should you store tokens?

3 mins |

January 22, 2021

Authenticating users is one of the basic features that we implement in almost every meaningful applications we build. It is one of the most important parts of any application, because of its security implications.

It is hard to get authentication right. So unless you are solving just for authentication, don’t build it yourself. You can pick services that provide authentication as a service like magic, Auth0, etc. If you want to host it yourself, most likely there would frameworks/libraries that are well maintained for the language you are using. If you go with the latter approach, you would have to manage the token somehow.

Basic authentication flow works like this.

+--------------------+ +-------------------+
| Client +------------+ Server |
+--------------------+ +-------------------+
➡️ 1. Request with credentials like username/password or tokens(refresh)
⬅️ 2. Response with token
➡️ 3. Subsequent requests with token
⬅️ 4. Validate the token and respond

Until the token expires, we keep the user authenticated.

After it expires, we have some mechanism to update the token based on the auth provider we use. eg.

  • you might have to provide the auth details again
  • re-new based on therefresh tokens
  • never expire the token

In all above situations we need to store the token somewhere. That is the challenge we face. Where do we store the token securely and send it back to the server?

These are two common choices and both of them have their pros and cons.

  1. Storage (Local/Session)
  2. Cookies

While using localstorage, the data stored in them can be accessed from client-side JavaScript. Which would mean, if for some reason, our window object is exposed, we give out a token to make authenticated requests. But with Storage the token is never sent “automatically” by the browser.

When it comes to Cookies, it kind of the opposite of Storage. We would be talking about httpOnly cookies otherwise, even cookies would be accessible from client-side JavaScript and it would be sent automatically. Making it a bad choice. With httpOnly cookies and marked as SameSite, these cookies would be sent automatically by the browser, but from client-side it wouldn’t be accessible.

So why is automatically sending cookies bad?

Since, token it automatically sent by the browser, any link to the site you are authenticated would give out information that only you should have access.

Let us assume you have logged into https://TrustedSiteIHaveLoggedIn.com/ ✅. And you accidentally clicked a link in a mail which took you to http://iwouldstealyourinfo.com/ ❌.

http://iwouldstealyourinfo.com/ ❌🤫 has a link in their page https://TrustedSiteIHaveLoggedIn.com/my-secret-info🤐 will give out all the secret from the site you logged into.

Some precautions taken to avoid such issues are Same Origin Policy (CORS). Recent releases of modern browsers also include SameSite in cookies which prevent the browser from automatically sending the cookie if it was not to be issued to the same domain.

Another problem is if a GET request is state changing. What it means is, the request would change something in your backend.

For eg. if you get a mail with link to a legit site https://TrustedSiteIHaveLoggediIn.com/transfer-all-money?to=GREEDY_GUY&amount=9999999. This link is a bad design, though “attacker” might not have access to your information they will be able to take actions through URLs. So to prevent such issues, don’t design any APIs which take an action through GET requests.

For state-changing requests like POST, just clicking browser makes GET request, so that gets prevented. Also, CSRF acts as additional security. As you send the additional token to make requests like POST

Why is accessing token from client-side JavaScript bad?

If a client-side JavaScript has access to the your token, any backdoor to access them like a window exposed by a bad external link.

E.g., it could happen if opening different site without explicitly preventing it by giving noopener noreferrer in your <a> tags or window.open.

In such cases, the third-party site can have access to your window. Which has access to localStorage, so does the token you have saved in the token.

So where should you keep the token?

If you are not sure about authentication, please don’t implement by yourself. It is an important part of any application you build. It has to be secure. If you can use third-party services, then use them. Here you don’t have many options on how or where to store these tokens.

If not, almost all frameworks/languages will have a reputed library to handle authentication. For NodeJS, it would be passportjs. In these implementations, you have the option of where to store these tokens.

I would recommend storing all long-living tokens (like session ids, refresh tokens) in Cookie with httpOnly and SameSite enabled. As additional security, based on the application and the library/module you are using you can enable CSRF.

For short-living tokens, don’t store them to any storage. Since they are active only for a few minutes (usually, 1-2mins), can be stored in a variable in your code.

I know I would be repeating myself 🙊, If you are not confident or you have no experience in building authentication for applications. Avoid implementing yourself, use some service or library.

Keep your application and your user’s information safe.

Got a Question? Bala might have the answer. Get them answered on #AskBala

Edit on Github

Subscribe Now! Letters from Bala

Subscribe to my newsletter to receive letters about some interesting patterns and views in programming, frontend, Javascript, React, testing and many more. Be the first one to know when I publish a blog.

No spam, just some good stuff! Unsubscribe at any time

Written by Balavishnu V J. Follow him on Twitter to know what he is working on. Also, his opinions, thoughts and solutions in Web Dev.