Hacker News new | past | comments | ask | show | jobs | submit login

But then it isn't stateless, right? Because you need to know which current tokens are unrefreshable.

To me, JWT works great for things like physical people getting access to a physically isolated building, like a military research site that's disconnected from the internet. Some secure other place holds the private key and signs the JWT token then you can wave in anywhere you need to go until the validity period is up. Then you have to go back to the secure place to get a new key, verifying the same way you did the first time and the secure place can broadcast its public key to the sites you want access to. It's essentially a great mechanism where you don't have constant communication links.

But I just don't get it for servers. Also, everyone considering using a JWT token should know about the "algorithm none" setting and ensure that their stack isn't vulnerable to it.




But then it isn't stateless, right? Because you need to know which current tokens are unrefreshable.

You only have to involve state in 1 request every 10-15 minutes upon refresh. All other requests can be done without having to check for revocation. This is a pretty nice real-world tradeoff.


While I haven't taken the leap to using a JWT in any of these cases yet and am a little bearish on them, I do also feel like the baby goes out with the bath-water, here.

Nothing about adopting JWT says you can't still use a full auth check for state-changing endpoints, and use a stateless session to shave some evaluation time off of frequent read-only requests for data that isn't terribly sensitive.

You probably shouldn't do it lightly or prematurely since it makes it harder to reason about authentication, but I think it's worth considering whenever you're optimizing.


Actually creating a JWT token is not stateless, but at least your architecture is not centralized. If your auth server goes down, that’s a problem no matter what.

A common validity period is around 1 hour, which is good enough that most users won’t need to refresh very many times per day.

Also: you don’t necessarily need to track tokens that aren’t refreshable. A typical architecture might have a timestamp stored per user that specifies the earliest token creation date that’s valid for refresh. That way you can invalidate all tokens without needing to ever store them; something you might need to do for password reset, for example.


> A typical architecture might have a timestamp stored per user that specifies the earliest token creation date that’s valid for refresh.

Never worked with JWTs but still, can't believe I didn't think of this. It seems like a fairly elegant way to revoke things where your only stored state is a timestamp.


> A typical architecture might have a timestamp stored per user that specifies the earliest token creation date that’s valid for refresh.

There's a race condition there, though. If you have a revocation event and set the timestamp, it's possible that an in-progress refresh might have a timestamp just slightly after your stored timestamp. Then you have a rogue JWT that can continue to be refreshed.

Clocks are sometimes not in sync with millisecond precision. Databases don't replicate instantly. Distributed systems just don't work that way.


You could instead store a "generation", and increment on revocation events


>algorithm none

I just read about it on Auth0 [0] and facepalmed. Then I went to node-jsonwebtoken to ensure they added an ‘algorithm’ argument to a ‘verify’ call and you guess what [1].

They added ‘algorithms’, but into ‘options’, so that naive user like me could just skip it and stay open to attacks. That’s auth0’s own module, btw.

Thanks for pointing that out!

[0] https://auth0.com/blog/amp/critical-vulnerabilities-in-json-...

[1] https://www.npmjs.com/package/jsonwebtoken#jwtverifytoken-se...


Use a proper JOSE module like https://www.npmjs.com/package/jose that uses native node's crypto key objects (ergo not leaving you vulnerable to HMAC based validation bypass) and doesn't even implement "none" algorithm.


You always have to authenticate the JWT anyways to verify data hasn't been changed. The stateless part is the fact that the sensitive data is stored in the JWT itself instead of retrieved from a DB. As long as you can validate the HMAC / Signature then you can assume the contents of the JWT haven't been altered and can therefore trust the client's data.


Authenticating JWT isn't checking the JWT against an external server.


How can you validate that it was properly signed without comparing it to the entity's public key?


Why would you need to make a request to another server for this purpose?

Hint: you don’t — but I figure taking the Socratic approach may be more convincing.


You could pre share a public key, but a common way is to use the discovery mechanism in OIDC to automatically manage key distribution/rolling.


Because else how do you handle key revocation?


Which is the point of the post.

If you need to do revocation you need to call an external server.

If you need to call an external server why do JWT?


Because pinging another server for a few bytes of data and offloading that working memory to the client side is much more efficient than storing the session data in server memory in between requests. Furthermore a single coordinating key server can work in conjunction with many micro-services to simplify architecture, security, and hardware requirements.


Which still leaves a window for JWT to be re-played. If you store something valuable, like # of credits left on a users account, the user can spend some, and then re-use an old jwt to spend again.


It’s stateful for the auth service, stateless for the relying party.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: