Where should you store tokens?
3 mins |
January 22, 2021Authenticating 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 the
refresh 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.
- Storage (Local/Session)
- 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
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