Should you put JWT in a cookie or local storage?
I am not sure if I should put the JWT I use for authentication in the response body or in a HTTP-Only and secure cookie. Which one is better for security and why?
I get this question very often and from a security perspective there is a very clear answer to that: Neither – simply because using JSON Web Signature tokens for client side session tokens is a flawed design.
Please note that when I talk about JWTs in the following article, I mean JSON Web Signature Tokens not JSON Web Encryption tokens.
Why JSON Web tokens don’t make good session tokens
Take a look at this video where I explain the pros and cons of sessions vs JSON Web Signature tokens for client side sessions.
Using JWTs as session tokens might be unacceptable in terms of security because you cannot log a user out from the server side or change the roles without introducing some sort of state.
JWTs are always a snapshot of the past. If you get a JWT (or a JSON web signature token to be precise) it basically tells you that at the time it was issued, the token was valid and the claims were valid – back then. Things could have changed, the token could have become invalid before its expiration.
Introducing state with JWTs on the server side for a simple login system defeats the purpose of having JWTs in the first place
Oftentimes people argue that you could implement some cache that holds a blocked list of tokens. Yes you could, but my question is: why would you do that? You are reinventing the wheel because you could have used sessions instead.
And if your blocked list cache crashes or is unavailable then the system might grant users access that might have been blocked. If you use sessions and your session storage is down, then your system is in a safe state. Noone can use it, but at least you are not vulnerable to attacks.
“But JWTs scale better”
Scale is also not really an argument for JWTs as session tokens because for probably 95 % of all companies using a “big enough” session store would be sufficient. In addition if you operate at massive scale, your bottleneck will most probably be your SQL database and not the size of your database session cache (e.g. Redis) because Redis is orders of magnitudes faster than any SQL database.
“But I don’t want sessions and I don’t want an additional session store”
Why not? I mean literally every web framework supports sessions with different external session stores out of the box. With that variety seeking behaviour you are potentially exposing your users and your business to significant risks. Choosing JWTs as session tokens just cannot be justified rationally.
You can be held liable for data breaches
As a developer and your CEO can be made personally liable in case a data breach has happened and in case an investigation uncovers that the implementation was grossly negligent and against common industry knowledge and security best practices.
It will be borderline impossible to explain to an auditor how you could oversee the fact that you cannot even log someone out server side.
“I don’t have to pay for a session store”
The only other argumentation that sounds kinda logical to me is if you say that you don’t want to maintain and pay for an additional session storage (like a Redis instance).
If a $10 Redis instance per month and maintenance is a concern, then chances are you are probably running a hobby or a small project with a small amount of users. if this is the case then you can just store the sessions inside of your main database. This is totally fine as long as you don’t have that many users. And then if you get more traffic (and let’s be honest, most web apps don’t) you can just pay for the Redis instance.
One more thing, son
And if all of that did not convince you, then let’s remember one thing. Authentication and Authorization are cross-cutting concerns – meaning noone cares about them as long as they work and as long as they are secure.
What we should care about is the actual business logic of the application we are building – the software that provides the actual value to the customer – because that is how you put food on the table. A customer will probably not rejoice when he sees a login screen. After all software always exists within a business context. Software is the tool that executes on the business model. It’s a tool and not a self-purpose.