Why JWTs Suck as Session Tokens

Calvin Nel

could you expand, how is session bad, surely you choose what tech? aka let say its a mobile app. Doesn’t make sense to sign in each time so use some sort of rolling auth, i can see why a token helps here, but still should expire or have a way of updating?, apps usually have limited scope in terms of functionality/configuring (permissions). but don’t see why it make sense for a website to use tokens. Say you have a website which has many custom features, and the menu as based on permissions, then how would you control this using jwt, would you add all the permissions to the jwt, and then ensure short expiry?

Thilo

The database as a single source of truth is in most cases the bottleneck when it comes to performance. Reducing the database requests by one per api request can have a significant impact on larger applications. Nevertheless JWT’s are overhyped and you should balance the pros and cons.

kim gysen

I don’t particularly understand how these things are a problem:
1) This is speculative. If the jwt is signed and TSL is used, you should be as good as the web can get. Moreover, cookies are also sent over the network. If you have XSS vulenerability, either session or jwt can suffer the same fate, you’re at the mercy of the intelligence / creativity of the attacker either way.
2) I don’t understand why you can’t create a server blacklist. ‘Then it’s stateful again’. I’m quite sure that black lists of blocked users should be a lot smaller than querying users from a user table. It seems very unlikely that you will ever need to scale those. What if the service goes down? Like any other system, you need load balancing or other ‘high availability’ mechanisms if you really think you need them. Makes you wonder about the same argument: how many websites are there that really need black lists, or instanteneous removal of users that can’t wait until expiry?
Then why use jwt? Because developers don’t like to worry about scalability, even though the truth may be that your website may never need to. But if jwt offers peace the benefit of peace of mind without downsides that sessions have, then why use sessions? Because they’re a bit smaller?

kim gysen

Indeed. Many concerns about this I don’t really get. You can use jwt for authentication without the need for session housekeeping at the server, and manage authorisation otherwise. It feels a bit like a witch hunt sometimes, glorifying session against jwt, but in the end jwt does have benefits regarding scaling and depending on how you use them, I really fail to see the problem after reading every related topic I get my hands on.

kim gysen

Another point I don’t really get. If a user logs out, you just throw away the token so there is nothing to authenticate with…

JOHN

Does this mean I have to hit a DB call every time a user needs to access a privileged API endpoint?

Andrew

This is a very bad take

grhuhggdjddd

Well for some “corner” cases jwt is ok, … but simple token “is” sufficient enough. Not to to mention all the jumbo you have to go through in every language to implement it.

Justine Mojal

Thank you!

Jiyuan Zheng

Nice article. it brought up a lot of the same points as I always think. People are abusing JWT without understanding its proper usage. It is good for exchanging information with third party or doing authentication. It is NOT a replacement for user session stored in server. Using JWT doesn’t change the fact you need to keep user state in your backend whether it’s in the server or a separate cache like Redis. If you are running an online store, you don’t want to store all the cart data in JWT and pass that back and forth in JWT.

Seer

The question is, if a JWT is used in a truly stateless manner (i.e. services trust the JWT just because it is signed) then how can it be invalidated without the owner of the token getting rid of it?

If the user chooses to log themselves out, yeah, it’d throw the token away - but that’s not the problem. What if some malicious individual gains access to a user’s account, and the real account owner wants to log that other person out? They wouldn’t be able to do it if it’s truly stateless.

One way that’s commonly handled is by making these tokens expire relatively quickly, and having to use another token (refresh token) to fetch a new, valid token again. That way you can revoke the refresh token, and when the first token (access token?) expires, the refresh token would no longer work. This mechanism also helps the case where permissions are changed. It’s not immediate though obviously, and it is basically like “caching” the data (just client-side, rather than server-side), so shares those problems.

Dubyah

It seems like the “How Should I Use JWTs?” walks back or contradicts your earlier points. Aren’t a large percentage of websites out there SPA websites? I’m a little confused by your inclusion of that category as for “acceptable” JWT after you mentioned you shouldn’t use them on most websites.

Can you add some clarification?

Muhammad Hussein Fattahizadeh

Reasons we should use:

* Scalable

* Authentication is first check is simple and easy to scale by adding more app behind reverse proxy, tell me about the scaling session storage is really pain in the a**.

* You can reduce hit on database for ACL by adding layer of Redis/LRU cache in app and then your ACL database.

* Encryption possible for JWT https://jose.readthedocs.io… but not necessary in most cases.
* In modern application you will need ACL framework from Back-end to Frontend solution, to check what they can CRUD. Session storage sucks on those most cases. Think about API with IOS/Android/SPA or even SSR view. https://casbin.org/

Marcello Kad Cadoni

Of course. Suppose that someone steal your device. You need to invalidate that token in some way.

Bok Woon Chua

Don’t like the JWT session fad. But if every request is guaranteed to hit the sessions table, the sessions table is really taking the brunt of the traffic. Of course, if you use a cache for sessions it would solve that problem entirely. JWT is bad because it is so poorly implemented with tons of footguns, the additional complexity is really not worth it. https://twitter.com/filosot…

Enzo Cheng

use another token (refresh token) to fetch a new, valid token again. That way you can revoke the refresh token, and when the first token (access token?) expires, the refresh token would no longer work.

So the refresh token is used before the access token expires or right when the access token expires?

Seer

Say your access token and refresh token have the same expiry time and it was 10 minutes, you could decide in your client application to refresh the access token at 5 minutes. This would give the client time to retry, and provide an uninterrupted experience to a user.

In reality the tokens may have different expiry times (e.g. 2 mins access token, 10 mins refresh). That’s often true because the access token is at greater risk of being intercepted (it’s sent more often) and it can do more damage (refresh tokens can only get a new access token, and should only be able to do it once). If a refresh token is stolen you can probably even detect that by the same refresh token being used twice, and in that scenario you could kill the session associated with those tokens.

SILENT

I don’t get this. What comparison does JWTs have with sessions? Its JWTs vs Cookies. Whats wrong with session JWTs? With session cookies, you need XSS and CSRF protection. With session JWTs, you only need XSS protection.

Stanley Sathler

Good article, Randall. I have 0 experience with tokens and general authentication methods, so this post brought me a few questions.

1. JWT has tons of concrete implementations. Node.js ecosystem has the jsonwebtoken lib. This lib abstracts the token generation, validation and expiration, right? If we don’t use JWT but Session Tokens, do we need to handle all these three items by ourselves?

2. We can carry extra information in a JWT - eg. a user id. Although this info is readable by anyone, it can’t be modified. This means we can safely rely on the user id provided by the token to fetch the user from the database, I guess. In the case of Session Tokens, from what I understood, you can carry extra information but this info can be modified, which means we need to “map” token to users somehow (eg. in our db). Is this reasoning right?

Thanks again for the awesome and clear explanation.

Michael Chung

JWT or access token is actually hard for newbies to implement on small projects without ending up implementing similar things as generating session IDs. If you want to follow the best practices, you can actually find people talking about different practices online, i.e. there may not be a consensus, and you will eventually get lost or over-engineer your project (i.e. doing crazy things like introducing refresh tokens which makes the architecture even more complicated and probably more prone to security issues).

Q1) By session token you are referring to session ID, and it is a proven technology that has been used for ages and is easy to implement. You will have to find out how to create sessions in your back-end, ideally using Redis as a centralized storage.

Q2) User ID (the “name” claim in JWT) is not an extra information because it is the most important information included in an access token. Without that, the resource server won’t knows who is performing the action. You are right about modification. The signature part (the 3rd part of the token string, after split by “.”) is an HMAC-SHA256 (for example, there are other choices) result of the 1st and 2nd parts of the token string, changing any part of the token string will result in either a broken signature or the signature being mismatch with the content. To produce the signature you will also need the secret from the identity providing server.
Regarding your point about a mapping between a user record and a session ID, yes the server maintains that mapping in something like a Redis cache.

You should watch Randall’s talk on YouTube to learn about using sessions first. Either one will do:
https://www.youtube.com/wat…
https://www.youtube.com/wat…