Why not just use cookies and be done with it? This looks like an advertisement for Redis Enterprise.
Alternatives? First, you could live with the possibility that tokens are valid for some period of time after logout because it usually doesn’t matter - generally you delete the cookie and the user is logged out, even if technically they could restore the cookie later. They won’t, unless you’re under attack.
Other alternatives: You could use Redis for session data as pointed out with the random key in a cookie and delete the session when done to invalidate the cookie.
You could also use Redis to keep token IDs that you want to invalidate or block. You could use something like Open Policy Agent to distribute a list of invalidated tokens to each server.
Finally, you could send your JWTs to a centralized authentication service — single point of failure, yes, but you could record invalidated tokens to memory and responses are very quick and easy to audit. With careful planning you could reduce the risks in having a single central service to validate issued tokens.
I’m sure there are other ways to mitigate this risk. The general reason why folks don’t recommend JWTs is because it’s too easy to make mistakes in the validation logic. But the same is true (with different possible mistakes) when you roll your own session cookies. At a certain point I think you have to either assume competence or you have to suggest that developers use identity proxies in the cloud, or frameworks others have written, and never implement this themselves.
But yes, this is a rather transparent advertisement for Redis as a KV session store.
The author argues that you can't revoke a JWT - suggesting that 30min is the usual default. To their point, if 30min is too long, then 10min is probably still too long.
However, implying that 30min is too long for a token to remain stale suggests that you aren't really working at the scale that JWT was destined to address (Facebook, Twitter, etc.). If you really are the unfortunate soul trying to solve per-request authz, specifically at the scale that JWT was designed for, then I feel deeply sorry for you. For the 99%, i.e. the rest of us, 30min is just fine.
> You could use Redis for session data as pointed out with the random key in a cookie and delete the session when done to invalidate the cookie.
I'm not picking at your argument, honestly, I'm just pointing out the absurdity of authz without JWT (or similar) at scale. Redis is eventually consistent: what happens during a network partition?
Saying that the JWT expiry is a vulnerability is tilting at windmills.
> The general reason why folks don’t recommend JWTs is because it’s too easy to make mistakes in the validation logic.
Bravo, that's the real problem with JWT right there: it's too easy to misuse - especially when convenience or demanding customers enter the picture. It also has brain-dead specification opportunities like signature-free tokens.
JWT expiration protects against situations where the token is stored (or made to be stored) somewhere improper and later used, not being pilfered during proper use.
As the article argues, it doesn't even protect against a malicious user using stale credentials to wreak havoc, such as a disgruntled employee that had access to the precious admin panel being fired.
> you could live with the possibility that tokens are valid for some period of time after logout because it usually doesn’t matter - generally you delete the cookie and the user is logged out, even if technically they could restore the cookie later. They won’t, unless you’re under attack.
That isn't why I don't recommend JWTs, and it's not why this article is not recommending JWTs.
> Logout doesn’t really log you out!
> Blocking users doesn’t immediately block them.
> Could have stale data
^ JWTs fundamentally are not compatible with server-side authentication revocation.
Your typical developer is like, "Well, I don't care much, I'll use JWTs anyway", but then some poor soul has to deal with the ticket titled "Blocked user still able to access service", or "User still able to access service after logout", or "session never expires!" (oo... look, you configured it incorrectly).
I've been on the other side of having to deal with screwed up JWT implementations other folk have built.
It's not fun.
...and yes yes, there are work arounds, you can have rotating short lived tokens and long lived refresh tokens and a database of revoked tokens...but you've just reimplemented server side session authentication yourself, and it's probably wrong.
> I think you have to either assume competence...
I think that's terrible advice. You should never assume developers are competent to implement authentication. It's a Hard Problem, like, writing a database, and frankly, only specialists are competent to do this correctly. Anyone can writing some kind of data store, but it's a bit harder having it ACID and concurrently multiuser.
> or you have to suggest that developers use identity proxies...
...but yes, this is probably the only useful piece of advice to give to people: If you use a 3rd party authentication provider, you can delegate responsibility for doing the hard work of making sure they have a solution for the hard things; at which point, you don't really care if its JWT or cookies, or whatever.
I still wouldn't recommend people use JWTs.
There's one important difference between session authentication and JWT+revocation: the revocation list can be distributed asynchronously, whereas a session list needs at least read-after-write consistency.
It's a minor point for most use cases, but occasionally can be very significant.
Not to be negative—if your JWT expires after 15 minutes and your list updates every 10 seconds, you’ve improved your reaction time quite a bit for revocations.
Also, you can have an eventually consistent session store if you don’t mind that sometimes users might see a 403 they shouldn’t, if your app can cover it up such as by requesting content from a different region or waiting a bit. Similar to the idea of using a load balancer to pin sessions to particular servers.
So it’s not that JWTs don’t have risks but the risks are overstated. It would be like saying never use Redis because by default it doesn’t have secure SSL or a proper password system and thus anyone could access it. Security isn’t easy, but it can be done, and often looks like a series of mitigations, monitoring tools and trade offs… such as how long sessions last, or planning for features like key rotation or session revocation in advance…
They are insecure but it's not a problem if you follow best practices like those, the difficulty is a lot of people don't because they don't really understand what it is they're doing or potentially causing by making the changes that let them be lazy or do things the easy way.
You could probably change the title to articles like this from "JWT Tokens are NOT safe" to "JWT Tokens are NOT safe when you ignore all security practices and take the easy way out" but that doesn't make for a flashy title.
Issuing your own JWTs also means you have to keep the secret or certificate used to sign them secure or if it leaks anyone could impersonate anyone else. This is especially problematic if admin or role assignment is embedded in the JWT.
JWT for short-lived tokens is fine - it can work well for signing requests between microservices. If you want to give them to end users, use refresh tokens.
As with anything, the alternative depends on your needs and use case. There is no universal solution.
I kinda agree it looks like an ad for redis, since it doesn't even considers alternatives.
[0] - https://hasura.io/blog/best-practices-of-using-jwt-with-grap...
All the good versions involve cookies somewhere - they’re the most resistant to all the various forms of attackers on the web.
Many use cookies in order to stamp short lived tokens, though.
Signed blobs of data such as certificates and web tokens are a very powerful massively distributed cache where the entity that benefits from the data being cached is also the entity responsible for persisting it. This is a wonderful optimization whose sole drawback is that you need an external way to decide when that entry is invalid. Solve that problem, don’t abandon the entire concept of the distributed cache.
(E.g. branding something is often a transition from people using language as a club against hunger, wild animals and the unknown to using it as a club against the other man.)
It is not unusual for systems like this to have some details such as verifying the cookie against the db if somebody is doing a critical operation and not being too worried about a five minute window for people reading articles and such.
High volume attacks need their own countermeasures.