Stop Using JWTs

dzonga 324 points 187 comments June 16, 2026
gist.github.com · View on Hacker News

Discussion Highlights (19 comments)

dzonga

due to the recent FIFA hack - just a reminder - stop using JWTs

solatic

Necessary qualifier: for browser-based user sessions. Plenty of good uses for JWTs for service-to-service communication. edit: I read some of the linked stuff, e.g. https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-ba... . Please, if JWTs are such a horrifically insecure standard, go ahead and publish your means for hacking AWS STS's AssumeRoleWithWebIdentity , or don't publish and just exploit it by launching cryptominers in every Fortune 500 production AWS account. Let me know when you inevitably succeed, because JWTs are so insecure, right? /sarcasm

ApolloFortyNine

This links to some other blog post for the bulk of it's 'why', and that blog post mostly seems to be annoyed about "You cannot invalidate individual JWT tokens". Which every time I've implemented, the general guideline is to check for invalidated nonces somewhere. Which resolves that random blog posts second point too. >The JWT specification itself is not trusted by security experts. This feels like it needs more evidence than just one blog post. And that blog post seems to just largely blame bad implementations? Something that will plague any standard. Overall, I don't know what I expected clicking a random gist link.

tracker1

JWTs are insecure... even when using trusted, rsa/ppk based signing methods? not shared secrets. JWTs are too long lived... Nothing is stopping you from limiting the JWT lifetime and having a refresh model against an authentication authority... I mean, even if you use cookie based sessions, you're storing somewhere... you can have a jwt valid for 5-15min. 15minutes is roughly the cache timing for many authorization systems including Entra... and even a 5min token with a refresh system can be used fine from a browser. Lastly, I prefer to have identity/auth separated from the application/api services... it externalizes context and JWT per request is easier to deal with than some shared cache/state system that may intermittently fail as opposed to a signed token that you can verify the signature against known authorities.

szmarczak

No need to stop. The XSS argument also applies when using cookies. JWTs are just tokens like session data but in JSON format. What format you choose to go with doesn't matter. You can keep storing JWTs in local storage and still be secure. Discord removes it on page load and restores it when the tab is closed. Also if your website is susceptible to XSS, skill issue, exactly like in the case of SQL injections. That wouldn't have happened had people used the right tools and not played with fire.

vova_hn2

One of the articles that TFA links to [0] contains the following paragraphs: > And there are more security problems. Unlike sessions - which can be invalidated by the server whenever it feels like it - individual stateless JWT tokens cannot be invalidated. By design, they will be valid until they expire, no matter what happens. This means that you cannot, for example, invalidate the session of an attacker after detecting a compromise. You also cannot invalidate old sessions when a user changes their password. > You are essentially powerless, and cannot 'kill' a session without building complex (and stateful!) infrastructure to explicitly detect and reject them, defeating the entire point of using stateless JWT tokens to begin with. I'm not sure that this is entirely true. Typically, the total number of non-expired issued tokens is much higher than the number of invalidated unexpired tokens. Therefore, if you store only invalidated tokens and delete them when they get expired, you can significantly reduce the amount of required storage and the cost of lookup. Although, in any real application the performance gains will be minuscule (compared to the cost of, you know, everything else. Auth is just a small part) and probably not worth the extra complexity. [0] "Stop using JWT for sessions" - http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-fo...

Grollicus

I'm right now adding rabbitmq for notification pushing to a website. Using JWT authentication to control where and what clients are allowed to read, with short lifetimes and regular token refresh. I don't see another setup that comes close to the ease of setting this up - add an endpoint that provides jwt tokens to valid sessions, done. With user-individual permissions.

hparadiz

JWTs are for authenticating an already trusted system with another system. Using them as the primary source of truth is an anti-pattern like the blog post is actually saying.

cjoelrun

I ain't never gonna stop!

hoppp

What if I put a jwt in a session cookie? The post is not descriptive enough It should explain how to not store JWT instead of just saying JWT is bad.

feelingsonice

PASETO is great but there's not enough ecosystem support

mgaunard

A whole lot of nonsense from a web guy. Please, keep using JWTs, they do their job well: giving you an access or ID token that you can pass between applications and trust based on cryptographic signatures from an identity provider.

miiiiiike

Security doesn't start or end with JWTs. A user wants to access a read-only resource with an invalid JWT? Envoy bounces it without passing the request through to the backend. Valid JWT? Let the request through without having to look up any session information. No DB, no cache, no session server hit. Fast. A user wants to change a password, email address, or add an authenticator? First, require a password, second, require a second factor. If all of that checks out, look for the JWT access token in a revocation list that is only accessed during sensitive, infrequent, requests like these. If the token has been revoked, 403. Tokens are dropped from the revocation list once the original access token's TTL has passed. Which should be low. I use 5 minutes. Most sessions on my site last 4-10 minutes. Worst case scenario, a malicious user is able to access certain read-only resources for a few minutes.

littlecranky67

In sessions vs. JWT revocation lists, there is an argument in favor of JWT revocation lists. JWTs have a limited expiry timestamp, so you only ever need to maintain a revocation list for tokens not expired yet. Given that you probably only have a fraction of JWTs revoked compare to valid JWTs in circulation, you only need to query a very small dataset for each request. When using sessions, your list of valid sessions is probably orders of magnitudes higher that the revocation list - thus the data lookup costs and the storage cost of that statefulness is higher. Plus, the article mentions JWTs are stateless but that is usually not true. You mostly not only validate the JWT, but also obtain a matching identity object (i.e. user details) for each request to see if the user is still enabled/authorized to do whatever he does. You can leverage stuff such as per-user revocation lists, or a minimum_issued_at that will validate any JWT iat field. This allows the "Logout from all devices" pattern, where that action will simply set a user's minimum_issued_at field to $NOW. All previous tokens will thus be revoked, without individuall revocation list checks.

kobalsky

I agree that using cookies is better for web sessions but I absolutely despise those using the boogeyman to shoo people away from stuff they don't like, instead of asking them to use their brains. > they are not secure. They are secure if they fit your risk profile, a blanket statement like this is just disinformation. Don't treat your peers like idiots.

misano

imo instead of random cookie u can carry some data in it and avoid more joins in database why not ?

lucassz

> You can't securely have truly stateless authentication without having massive resources, see the cryto.net link above. I don't think the cryto.net post really explains why this is true (at least in a way that would be made different by "massive resources").

adamddev1

I remember learning to make sites back around 2019 and seeing so many blog posts and hype around JWTs. It seemed like "this was the way to do it!" But I couldn't understand why session cookies weren't the better, simpler solution. I just used session cookies. Nice to be vindicated in retrospect.

blixt

JWTs are fine, seems a bit sensationalist title... Some nice topics to talk about instead: - When to use an encrypted value (and symmetric or asymmetric), vs. a random (but secret) value, vs. a signed value (readable but not tamperable) - Where to put these values (memory, localStorage, cookies) - How to make sure these values don't last forever, and whether you need to be able to revoke them (make them invalid before their natural expiration timestamp)

Semantic search powered by Rivestack pgvector
10,715 stories · 100,765 chunks indexed