This article is completely AI-generated, anyone who reads LLM output often can confirm that. And Pangram confirms it as well. It's one of the more reliable LLM detectors and has an extremely low false positive rate, although in this case it marked Markdown parts too (they're irrelevant since it's a web article, not a normal post).
The same criticism can be leveled against a signed session token. Also comparing decryption with a local redis get which is still much slower is wrong. The criticism against long expiration is valid but that is not unique to JWT, and token refresh is not a "patch" on a broken system. This is just way off on everything
I'm sure those 80 microseconds are going to ruin the performance of that WordPress/Django app!
Why would you want to deal with a bespoke session and authentication table when there's a standard solution out there already? What's the point in figuring out your custom little cookie signature system when every frontend and backend under the sun have a solution ready to go? And somehow, somewhere, Redis is now part of the design to prevent having to do a database round trip for every cookie?
Sounds to me like this is a whole load of work for little benefit. Sure, session cookies just work most of the time, but they have their own disadvantages.
The only tangible benefit to session cookies is that you can log out all existing sessions at the cost of doing a lookup for every request. Most websites don't even offer that functionality, though.
This is badly written? I was gonna try to argument but it just sound like the writer had a bad day configuring a project IAM and put a generic rant online about JWT usage...
If your frontend application connects to multiple protected APIs, you just can't use a session. That's it. Mobile apps and some specific web application need this a lot.
The only true claim I see in this post is
> almost every developer shipping it has no idea why.
That's the true problem. JWT is being used as a SSO strategy in the wrong way most of the times.
JWT can be short-lived, for example 1 hour. Then on each request if the token is nearing expiration you decide whether to extend it or not, and if so return a replacement JWT with extended expiration. With a short-lived JWT you don't need to invalidate the JWT.
> just put the JWT in an httpOnly cookie
You can have two cookies, one that is signed and httpOnly, and another that is unsigned and readable by JavaScript. Both contain the same information. So JavaScript can read the information in the second cookie, but since it is unsigned, exfiltrating the cookie doesn't compromise security.
Let's say a friend sends you an exe file, a game they made. You run it, and immediately realize it wasn't actually your friend. The attacker has stolen your JWT session cookie. The attacker hasn't done anything yet - they are configuring their browser cookies to match yours. You go to invalidate your session / change your password, but it doesn't help. The attacker has a full hour to do whatever they want on your account. They use it to send the same malicious exe from your account. If you would've been able to invalidate the session, you could've stopped it.
The example requires immediate action. If the hacker beats you he can lock you out by taking over the account, it doesn't matter if it is JWT or some other tech.
Why would it require immediate action? Most chat services have a rate limit, stopping them at ANY point prevents it from spreading further. The messages don't get all sent at once, they will use the full access period to send as much as they can. Accounts can't typically be taken over with just a cookie, changing passwords normally requires you to confirm your current one. I hope you haven't designed any services where a cookie is enough to lock people out.
Geez, I need to re-sign in every time my mobile data switches IP?? IPs are NOT static. Mobile networks change IPs CONSTANTLY. What if I use a VPN (I do) and my IP changes constantly? What if an IOT device on your network is serving as a public residential proxy that anyone can use (more common than you may think), or hell, you have CGNAT and your neighbor does? What if an entire country only goes through one IP[1]? Have you done this in practice?
Still the same problem, if your account is compromised, you cannot invalidate the session, same for web, same for native app. You need to store it so that it can be blacklisted.
What about the other claims, aud and iss for example. And automatically being able to validate those tokens through OIDC?
And don't pretend that the 2 are not related because typically an OIDC provider is the thing issuing those JWTs.
So, can you simplify, sure. And now every part of your application needs access to that same table of sessions to get revocation.
It works fine for simple applications not for large solutions with many different systems that cross org boundaries. Because in a lot of orgs the boundaries of the services are more organizational than technical. If you want to be the one that makes them all depend on your SPOF, go ahead, I want to see you sell that idea to your CTO
Skill issue. I personally implemented the Minecraft Auth flow with JWT, and it handles ~250k req/s. It has the added benefit that already logged in users are unaffected if the Auth service goes down(Minecraft is a popular target for script kiddies and ddos attacks, so shit happens).
The entire argument the article does about invalidation confirms this: the bit about 5 year tokens. You do automatic token refreshes, which requires 5 extra lines of code on the client, and one network request every 30 minutes or so. Log out? Remove the token from the client, and let it expire in the next <30 minutes. Safe enough for most use cases.
It's fine to default to jwt, but yeah obviously you can screw it up if you implement it bad enough, and there are certain use cases where token expiry might not be safe enough (banking for example. But honestly with a short enough TTL it might be fine even there. You can totally do 5 minute tokens with automatic refresh gated behind user activity, if you need tighter security)
In the per-request cost table the author complains that signature validation is expensive, yet it's ~half the cost of a redis lookup according to the same table!
To me the entire article sounds like arguing that running shoes are bad because the author got a belly ache after eating one.
I think the perspective is most systems don't need validation based security, only access based security.
So it's fine for some services to serve requests after the access has been revoked for a few extra minutes or seconds.
For some it isn't. I have no say on the matter, I feel like security lax-ness makes sense for games, since jacking sessions with jwt is significantly less consequential and you have other sources to validate session health, such as route and ip address.
You can always revoke jwt if the ip address for which it was issue has changed or the route is different and so on and can be even more secure against forgery attacks.
Still not perfect and I find OP's take the it's good enough for banking to be sus.
But it's definitely not a scam, it's simple easy and trivial to use for a lot of low risk services.
You should build a map of low risk and high risk access and not use jwt for anything high risk, because jwts definitely provider better user experience for relatively less effort and resources and technical complexity needed.
It's not 30 minutes of unauthorised access, it's 30 a minute window where you have some extra attack surface. It's safe enough because exploiting that small attack surface within the timelimit is sufficiently hard that it can be considered safe.
Of course the only completely hack-proof device is a brick.
Typical production architecture would look like
- frontend only ever sees an opaque session cookie
- bff stores the access token against session and attaches it when calling backend services
Yes, storing JWTs directly in the frontend client is a bad idea but surely there is a better way of communicating that than "JWT is a scam and your app doesn't need it".
> RS256 verification is in the same order of magnitude as a Redis lookup
But the point is that the verification is CPU bound and local to the service - which means that it is horizontally scalable.
The article doesn't need clickbait titles either, which is also not a savory practice. Other than that it is good to educate people to make informed decisions on JWT.
I think JWT-like schemes can enable better machine-to-machine integration.
If you drink all of the koolaid, you can wind up with a system where two different parties securely authenticate sessions without any kind of secrets ever needing to be provided directly. Both parties generate and retain private key material in an HSM and perform signing ops there. The only thing that has to be trusted is the subject of the certificates. Keys can be rotated arbitrarily and the counterparty should not have any issues with this, assuming the standards are followed.
Short lifetime is the best solution to concerns around revocation. The vendor I last integrated with has their opaque tokens expire after 15 minutes. Immediate revocation sounds preferable but in practice there are other controls that will typically compensate for any gaps here (i.e., audit logs & the police). If you are firing someone and you think they might do a really bad thing that the business could never recover from, you should probably disable their accounts about an hour before the call with HR.
It's so easy to have an LLM generate your blog post without meandering in circles and without all the LLM tells, so why not do it?
I mean, honestly, there are really only two options here:
1. You don't know how to "tune" the LLM output, or
2. The LLM output can't be tuned.
Either one means that you should probably write your own thoughts and not have a probabilistic generator create this word-salad that I found extremely hard to follow!
I have a pile of personal criticisms of jwt, but I don't think this article does a great job of arguing against JWTs. For example:
> You can't [invalidate a jwt]. That's the answer. The token is valid until it expires, full stop. The only way to invalidate it is to store the jti server-side in a revocation list and check that list on every single request.
...So the article says you can't invalidate a jwt, and not 2 sentences later, tells you how you can. Of course you can.
> [misc criticisms of refresh tokens]
Mostly agree with this part.
> RS256 verification is in the same order of magnitude as a Redis lookup. And you still have to parse JSON, validate exp, validate iss, validate aud, walk the JWKS cache for the right key, and allocate a few objects the GC has to clean up later. Multiply by your request rate.
I think this misses the mark a bit. Signing/validating a jwt can be done entirely on your application server, which should easily scale horizontally. Any kind of db lookup requires a roundtrip/bottleneck which introduces complexity. So, even if it's the same # of ms, there's still an inherent advantage for validating on your application server IMO.
> Almost no one does [front end verification]
Sure, agreed, but so what? It's a feature that no one uses. That doesn't invalidate other features of jwts.
> The advice goes: don't put the JWT in localStorage because XSS will steal it — put it in an httpOnly, Secure, SameSite cookie so JavaScript can't touch it. Read that sentence one more time. You have just described a session cookie. The browser attaches it automatically, the server reads it on every request, the client can't see what's inside.
Yes, I think from a client perspective, it's fine to think of it like just a session cookie. As many other commenters have pointed out though, it's like a session cookie _with super powers_ because once the request is validated by some kind of front end app server, you can pass that same token around to other backend server and trust the claims inside it and save each of those services from having to do their own lookup. This I Think is the real value of JWTs over plain ol' session cookies.
How often do we need to revoke individual JWTs anyway? You solve for cookie theft with short expiry and key compromise by rotating keys. I don’t find the revocation issue very compelling as a reason to ditch JWTs.
Is revocation really such a hard problem? Seems you could store a set of revoked tokens in memory and have a background task update it every couple of seconds. I guess it’s a separate set of infrastructure to maintain but I don’t see why it’s always presented as the thing that undermines an entire authentication scheme.
I guess if you need your tokens revoked this millisecond it’ll require an extra synchronous call on every request but that seems like a unlikely requirement.
Eh. JWTs are super handy if you have a single web experience spread across multiple backend apps on the same domain, with a single SSO server to set up the user auth. Definitely not for storing anything sensitive, but treating it like a fancy session cookie with the minimal amount one needs to securely access resources - customerId or whatever - makes life a lot easier than trying to wire up cookie / session management across a lot of different, disparate apps.
How that is possible, when every web framework has a package for handling sessions, and in a secure manner. Rolling everything on your own is time consuming and error prone. I know you should not use library for everything, but this is solved problem for a long long time (like crypto), and just using of the shelf solution is right choice to me. You can set the session to be across multiple subdomains and it will work out of the box.
Eveything else can use plain tokens stored in the DB
Yeah... but you can't just move a session across a heterogeneous set of servers with different backends, etc... Maybe some of your APIs are on one platform, the apps themselves on another. There are several libs that can help you do that.
What are you talking about? Good frameworks have support for using guards on endpoints. Typically you add an annotation to the handler and that's it - and your system is then going to be much more secure than most alternative approaches, because the simple one-line guard ensures that only users who are authorized to access a specific resource can access it.
You just haven't understood what JWTs are good for. See my other comment in this thread.
This post needs an important clarification, which is that it's talking about using JWT for authentication, not authorization.
The uses described in the article assume that authorization of access to resources is handled in some way external to the JWT. This literally takes a system designed to support authorization, ignores that, and uses some other back-end authorization mechanism.
One of the most important features of JWT is its support for capability security[1], via signed claims. If you're just using JWT to authenticate, you're kind of missing the point.
> The payload usually holds a user id, an iat, an exp, a jti, maybe some scopes.
This demonstrates the point nicely. At best, scopes provide some sort of broad authorization such as "read" or "write". But what if you want to prevent IDOR attacks[2] at a low level in your system, to eliminate any possibility of developers accidentally allowing them? Tokens with nothing more than scopes don't help with that at all.
All you need to do to solve that is to add the entity types and IDs that the bearer is authorized to access. So if they're going to a page that displays an invoice, then in the JWT claims you include "invoiceId" (often along with some kind of type field, like "type": "invoice".) The target page checks that the JWT matches the requested resource, and that can indeed be done without any further back-end verification. You would also typically include a tenant ID and other such authorizing identifiers.
Doing this alone will give a system stronger security than 99.9% of systems out there.
Regarding revocation, the point about the above approach is that the tokens are essentially single-use: they authorize access to a particular resource for a short period of time. Basically, whatever the normal "log user out after inactivity" timeout is, the token expiry should be no longer than that.
If you create tokens valid for days or weeks, that's a mistake. You can prevent this simply by giving devs a library that creates the tokens according to org policy.
So yeah, JWTs purely for authentication and doing authorization some other way is a dumb idea, but that doesn't make JWTs a scam, that makes the user ignorant of their real purpose.
Friendly reminder: Some nuclear silo facilities in the US still use 3,5" diskettes. Some highly complex system are by architecture, security issues or by incompetence still stuck in decades old tech. We as engineers oftentimes have to work with that, and keep the system running, if we like it or not.
You cannot refactor an battlecarrier designed in 1979 so easily ;)
It's not, it's just something that I've had problem with a long time. Not everything is AI generated, and I hate if someone writes AI articles especially something important like this. These are my general thoughts about it, everything here that I explained is the things I've seen in the wild, and what people are doing. I'm just fed up with it
One thing that I did AI generate is the website itself. I really didn't have the time to do it on my own and I vibe coded it
Why are you openly lying to others, on HN out of all places?
> A single opaque token, looked up in Redis with Postgres as the backing store, gives you the same security in one line of middleware. No refresh. No second token. No retry loop. Nothing.
This is one classic example of LLM writing, humans don't write like this. The blog post has tens of other tells.
This article is completely AI-generated, anyone who reads LLM output often can confirm that. And Pangram confirms it as well. It's one of the more reliable LLM detectors and has an extremely low false positive rate, although in this case it marked Markdown parts too (they're irrelevant since it's a web article, not a normal post).
https://www.pangram.com/history/c68104cd-6072-4f7a-850b-e534...
The same criticism can be leveled against a signed session token. Also comparing decryption with a local redis get which is still much slower is wrong. The criticism against long expiration is valid but that is not unique to JWT, and token refresh is not a "patch" on a broken system. This is just way off on everything
I'm sure those 80 microseconds are going to ruin the performance of that WordPress/Django app!
Why would you want to deal with a bespoke session and authentication table when there's a standard solution out there already? What's the point in figuring out your custom little cookie signature system when every frontend and backend under the sun have a solution ready to go? And somehow, somewhere, Redis is now part of the design to prevent having to do a database round trip for every cookie?
Sounds to me like this is a whole load of work for little benefit. Sure, session cookies just work most of the time, but they have their own disadvantages.
The only tangible benefit to session cookies is that you can log out all existing sessions at the cost of doing a lookup for every request. Most websites don't even offer that functionality, though.
This is badly written? I was gonna try to argument but it just sound like the writer had a bad day configuring a project IAM and put a generic rant online about JWT usage...
If your frontend application connects to multiple protected APIs, you just can't use a session. That's it. Mobile apps and some specific web application need this a lot.
The only true claim I see in this post is > almost every developer shipping it has no idea why.
That's the true problem. JWT is being used as a SSO strategy in the wrong way most of the times.
You dont need jwt so that you can authenticate API or Mobile app. people were doing exactly that long before JWT was invented.
It's badly written because it's completely LLM-generated.
JWT can be short-lived, for example 1 hour. Then on each request if the token is nearing expiration you decide whether to extend it or not, and if so return a replacement JWT with extended expiration. With a short-lived JWT you don't need to invalidate the JWT.
> just put the JWT in an httpOnly cookie
You can have two cookies, one that is signed and httpOnly, and another that is unsigned and readable by JavaScript. Both contain the same information. So JavaScript can read the information in the second cookie, but since it is unsigned, exfiltrating the cookie doesn't compromise security.
Let's say a friend sends you an exe file, a game they made. You run it, and immediately realize it wasn't actually your friend. The attacker has stolen your JWT session cookie. The attacker hasn't done anything yet - they are configuring their browser cookies to match yours. You go to invalidate your session / change your password, but it doesn't help. The attacker has a full hour to do whatever they want on your account. They use it to send the same malicious exe from your account. If you would've been able to invalidate the session, you could've stopped it.
> and immediately realize
That's a narrow scenario isn't it, if you have to "immediately" realize?
No, it's called an example. I refuse to provide an example for every possible scenario, as that would not fit in the Hacker News comment limit.
The pattern described is a common Discord account theft method and it has proven very effective at locking people out of their accounts.
The example requires immediate action. If the hacker beats you he can lock you out by taking over the account, it doesn't matter if it is JWT or some other tech.
Why would it require immediate action? Most chat services have a rate limit, stopping them at ANY point prevents it from spreading further. The messages don't get all sent at once, they will use the full access period to send as much as they can. Accounts can't typically be taken over with just a cookie, changing passwords normally requires you to confirm your current one. I hope you haven't designed any services where a cookie is enough to lock people out.
Add a client IP field to the JWT. Token is only valid if the request comes from the associated IP. Done.
Geez, I need to re-sign in every time my mobile data switches IP?? IPs are NOT static. Mobile networks change IPs CONSTANTLY. What if I use a VPN (I do) and my IP changes constantly? What if an IOT device on your network is serving as a public residential proxy that anyone can use (more common than you may think), or hell, you have CGNAT and your neighbor does? What if an entire country only goes through one IP[1]? Have you done this in practice?
[1] https://en.wikipedia.org/wiki/User:82.148.97.69
Still the same problem, if your account is compromised, you cannot invalidate the session, same for web, same for native app. You need to store it so that it can be blacklisted.
What about the other claims, aud and iss for example. And automatically being able to validate those tokens through OIDC?
And don't pretend that the 2 are not related because typically an OIDC provider is the thing issuing those JWTs.
So, can you simplify, sure. And now every part of your application needs access to that same table of sessions to get revocation.
It works fine for simple applications not for large solutions with many different systems that cross org boundaries. Because in a lot of orgs the boundaries of the services are more organizational than technical. If you want to be the one that makes them all depend on your SPOF, go ahead, I want to see you sell that idea to your CTO
Skill issue. I personally implemented the Minecraft Auth flow with JWT, and it handles ~250k req/s. It has the added benefit that already logged in users are unaffected if the Auth service goes down(Minecraft is a popular target for script kiddies and ddos attacks, so shit happens).
The entire argument the article does about invalidation confirms this: the bit about 5 year tokens. You do automatic token refreshes, which requires 5 extra lines of code on the client, and one network request every 30 minutes or so. Log out? Remove the token from the client, and let it expire in the next <30 minutes. Safe enough for most use cases.
It's fine to default to jwt, but yeah obviously you can screw it up if you implement it bad enough, and there are certain use cases where token expiry might not be safe enough (banking for example. But honestly with a short enough TTL it might be fine even there. You can totally do 5 minute tokens with automatic refresh gated behind user activity, if you need tighter security)
In the per-request cost table the author complains that signature validation is expensive, yet it's ~half the cost of a redis lookup according to the same table!
To me the entire article sounds like arguing that running shoes are bad because the author got a belly ache after eating one.
Can you explain how 30 minutes of unauthorized access is safe enough for most use cases? I feel like you glossed over that.
I think the perspective is most systems don't need validation based security, only access based security.
So it's fine for some services to serve requests after the access has been revoked for a few extra minutes or seconds.
For some it isn't. I have no say on the matter, I feel like security lax-ness makes sense for games, since jacking sessions with jwt is significantly less consequential and you have other sources to validate session health, such as route and ip address.
You can always revoke jwt if the ip address for which it was issue has changed or the route is different and so on and can be even more secure against forgery attacks.
Still not perfect and I find OP's take the it's good enough for banking to be sus.
But it's definitely not a scam, it's simple easy and trivial to use for a lot of low risk services.
You should build a map of low risk and high risk access and not use jwt for anything high risk, because jwts definitely provider better user experience for relatively less effort and resources and technical complexity needed.
It's not 30 minutes of unauthorised access, it's 30 a minute window where you have some extra attack surface. It's safe enough because exploiting that small attack surface within the timelimit is sufficiently hard that it can be considered safe.
Of course the only completely hack-proof device is a brick.
Who uses JWT like this anyway?
Typical production architecture would look like - frontend only ever sees an opaque session cookie - bff stores the access token against session and attaches it when calling backend services
Yes, storing JWTs directly in the frontend client is a bad idea but surely there is a better way of communicating that than "JWT is a scam and your app doesn't need it".
> RS256 verification is in the same order of magnitude as a Redis lookup
But the point is that the verification is CPU bound and local to the service - which means that it is horizontally scalable.
> JWT is a scam
The article doesn't need clickbait titles either, which is also not a savory practice. Other than that it is good to educate people to make informed decisions on JWT.
I think JWT-like schemes can enable better machine-to-machine integration.
If you drink all of the koolaid, you can wind up with a system where two different parties securely authenticate sessions without any kind of secrets ever needing to be provided directly. Both parties generate and retain private key material in an HSM and perform signing ops there. The only thing that has to be trusted is the subject of the certificates. Keys can be rotated arbitrarily and the counterparty should not have any issues with this, assuming the standards are followed.
Short lifetime is the best solution to concerns around revocation. The vendor I last integrated with has their opaque tokens expire after 15 minutes. Immediate revocation sounds preferable but in practice there are other controls that will typically compensate for any gaps here (i.e., audit logs & the police). If you are firing someone and you think they might do a really bad thing that the business could never recover from, you should probably disable their accounts about an hour before the call with HR.
K, I'll stop authorizing incoming OAuth 2 requests to Amazon AgentCore by validating JWTs before allowing access to agents and gateways.
JWTs are very helpful if you maintain many downstream services on separate domains that need shared auth and identity infrastructure
> The rest of this post is me showing my work.
No, the rest of the post was written by an LLM.
It's so easy to have an LLM generate your blog post without meandering in circles and without all the LLM tells, so why not do it?
I mean, honestly, there are really only two options here:
1. You don't know how to "tune" the LLM output, or
2. The LLM output can't be tuned.
Either one means that you should probably write your own thoughts and not have a probabilistic generator create this word-salad that I found extremely hard to follow!
I have a pile of personal criticisms of jwt, but I don't think this article does a great job of arguing against JWTs. For example:
> You can't [invalidate a jwt]. That's the answer. The token is valid until it expires, full stop. The only way to invalidate it is to store the jti server-side in a revocation list and check that list on every single request.
...So the article says you can't invalidate a jwt, and not 2 sentences later, tells you how you can. Of course you can.
> [misc criticisms of refresh tokens]
Mostly agree with this part.
> RS256 verification is in the same order of magnitude as a Redis lookup. And you still have to parse JSON, validate exp, validate iss, validate aud, walk the JWKS cache for the right key, and allocate a few objects the GC has to clean up later. Multiply by your request rate.
I think this misses the mark a bit. Signing/validating a jwt can be done entirely on your application server, which should easily scale horizontally. Any kind of db lookup requires a roundtrip/bottleneck which introduces complexity. So, even if it's the same # of ms, there's still an inherent advantage for validating on your application server IMO.
> Almost no one does [front end verification]
Sure, agreed, but so what? It's a feature that no one uses. That doesn't invalidate other features of jwts.
> The advice goes: don't put the JWT in localStorage because XSS will steal it — put it in an httpOnly, Secure, SameSite cookie so JavaScript can't touch it. Read that sentence one more time. You have just described a session cookie. The browser attaches it automatically, the server reads it on every request, the client can't see what's inside.
Yes, I think from a client perspective, it's fine to think of it like just a session cookie. As many other commenters have pointed out though, it's like a session cookie _with super powers_ because once the request is validated by some kind of front end app server, you can pass that same token around to other backend server and trust the claims inside it and save each of those services from having to do their own lookup. This I Think is the real value of JWTs over plain ol' session cookies.
How often do we need to revoke individual JWTs anyway? You solve for cookie theft with short expiry and key compromise by rotating keys. I don’t find the revocation issue very compelling as a reason to ditch JWTs.
You have never used "Log me out from everywhere" feature. I've used it. Also it's for I want to change my password and invalidate all sessions.
Is revocation really such a hard problem? Seems you could store a set of revoked tokens in memory and have a background task update it every couple of seconds. I guess it’s a separate set of infrastructure to maintain but I don’t see why it’s always presented as the thing that undermines an entire authentication scheme.
I guess if you need your tokens revoked this millisecond it’ll require an extra synchronous call on every request but that seems like a unlikely requirement.
I don’t recall ever in my life using that feature on the small number of services that offer it.
JWT is fine. The problem is that people are using it for the wrong problems, like session cookies. But that has nothing to do with JWT.
Eh. JWTs are super handy if you have a single web experience spread across multiple backend apps on the same domain, with a single SSO server to set up the user auth. Definitely not for storing anything sensitive, but treating it like a fancy session cookie with the minimal amount one needs to securely access resources - customerId or whatever - makes life a lot easier than trying to wire up cookie / session management across a lot of different, disparate apps.
How that is possible, when every web framework has a package for handling sessions, and in a secure manner. Rolling everything on your own is time consuming and error prone. I know you should not use library for everything, but this is solved problem for a long long time (like crypto), and just using of the shelf solution is right choice to me. You can set the session to be across multiple subdomains and it will work out of the box.
Eveything else can use plain tokens stored in the DB
Yeah... but you can't just move a session across a heterogeneous set of servers with different backends, etc... Maybe some of your APIs are on one platform, the apps themselves on another. There are several libs that can help you do that.
What are you talking about? Good frameworks have support for using guards on endpoints. Typically you add an annotation to the handler and that's it - and your system is then going to be much more secure than most alternative approaches, because the simple one-line guard ensures that only users who are authorized to access a specific resource can access it.
You just haven't understood what JWTs are good for. See my other comment in this thread.
This post needs an important clarification, which is that it's talking about using JWT for authentication, not authorization.
The uses described in the article assume that authorization of access to resources is handled in some way external to the JWT. This literally takes a system designed to support authorization, ignores that, and uses some other back-end authorization mechanism.
One of the most important features of JWT is its support for capability security[1], via signed claims. If you're just using JWT to authenticate, you're kind of missing the point.
> The payload usually holds a user id, an iat, an exp, a jti, maybe some scopes.
This demonstrates the point nicely. At best, scopes provide some sort of broad authorization such as "read" or "write". But what if you want to prevent IDOR attacks[2] at a low level in your system, to eliminate any possibility of developers accidentally allowing them? Tokens with nothing more than scopes don't help with that at all.
All you need to do to solve that is to add the entity types and IDs that the bearer is authorized to access. So if they're going to a page that displays an invoice, then in the JWT claims you include "invoiceId" (often along with some kind of type field, like "type": "invoice".) The target page checks that the JWT matches the requested resource, and that can indeed be done without any further back-end verification. You would also typically include a tenant ID and other such authorizing identifiers.
Doing this alone will give a system stronger security than 99.9% of systems out there.
Regarding revocation, the point about the above approach is that the tokens are essentially single-use: they authorize access to a particular resource for a short period of time. Basically, whatever the normal "log user out after inactivity" timeout is, the token expiry should be no longer than that.
If you create tokens valid for days or weeks, that's a mistake. You can prevent this simply by giving devs a library that creates the tokens according to org policy.
So yeah, JWTs purely for authentication and doing authorization some other way is a dumb idea, but that doesn't make JWTs a scam, that makes the user ignorant of their real purpose.
[1] https://en.wikipedia.org/wiki/Capability-based_security
[2] https://cheatsheetseries.owasp.org/cheatsheets/Insecure_Dire...
> I am tired of pretending JWT is fine.
I don't get it. Why were you lying to people??? Why were you pretending? Thats not healthy and pretty anti-social.
That's how cargo-culting works.
Who’s still on x86 in 2026?
Friendly reminder: Some nuclear silo facilities in the US still use 3,5" diskettes. Some highly complex system are by architecture, security issues or by incompetence still stuck in decades old tech. We as engineers oftentimes have to work with that, and keep the system running, if we like it or not.
You cannot refactor an battlecarrier designed in 1979 so easily ;)
Who is not, X86_64 is an extension to X86. Same thing, no need to nitpick
Why post this AI-generated article? Just to ragebait?
It's not, it's just something that I've had problem with a long time. Not everything is AI generated, and I hate if someone writes AI articles especially something important like this. These are my general thoughts about it, everything here that I explained is the things I've seen in the wild, and what people are doing. I'm just fed up with it
One thing that I did AI generate is the website itself. I really didn't have the time to do it on my own and I vibe coded it
Why are you openly lying to others, on HN out of all places?
> A single opaque token, looked up in Redis with Postgres as the backing store, gives you the same security in one line of middleware. No refresh. No second token. No retry loop. Nothing.
This is one classic example of LLM writing, humans don't write like this. The blog post has tens of other tells.