In 2018 it is fully possible to use authentication libraries which natively support granular control for things like revocation using strong, turnkey cryptography. I would argue most people who think they should be using stateless and signed sessions for e.g. performance are heavily discounting the revocation liability and neglecting to optimize their lookups sufficiently (such as by caching).
That statement is false.
JWT were specifically designed to store a payload JSON object which among the many standardized fields include the token's expiry time, and JWT were specifically designed with a workflow which includes not only client-side token refreshing but also server-side token rejection that triggers client-side token refreshes.
In fact, JWT token refreshes and token rejections feature in any basic intro tutorial to JWT, including the design principle that tokens should be discarded and refreshed by the client as soon as possible and also the use of nonces.
The exp payload field is even specified in JWT's RFC along with the token rejection workflow.
https://tools.ietf.org/html/rfc7519
The same document also specifies the jti field which is the JWT's nonce.
And the jti field is not intended for what you think it is. Anti-replay is not at all the same as revocation. Those are different things entirely.
I certainly believe (and have seen) the jti field used in the manner you describe. But no, that workflow is not intended for revocation. Which makes sense given the design intentions of JWT, because anti-replay can be accomplished as a stateless process, while revocation cannot.
Issue and expiration timestamps are used along with nonces to enforce single use tokens. Once a token is used then the client is expected to discard and refresh the token.
Implementations are also free to keep track of issued tokens and that does not pose any problem in the real world.
> And the jti field is not intended for what you think it is. Anti-replay is not at all the same as revocation.
Why are you expecting to revoke a token in a scenario where the token is supposed to be used once?
Either the token is deemed valid and accepted or it's invalidated and rejected, which triggers clients to refresh the token and retry the request.
An attacker was able to somehow issue a bunch of tokens for himself. Now you want to invalidate them even though they're not used yet.
> Either the token is deemed valid and accepted or it's invalidated and rejected, which triggers clients to refresh the token and retry the request.
The other point here is that you are probably (not always, not in every possible case, but in most common cases) better off using just a bearer token (refresh it on every use if need be). There's no performance benefit in using stateless tokens when they can be used only once, and handling bearer tokens is much easier from a gun-to-shoot-your-feet-with perspective.
I'm not expert in JWT and just jumping in here, but wouldn't that imply total compromise of the PKI if this ever happens?
I'm saying, if this scenario comes to pass, with basically any old authentication system, isn't it now time to roll the master keys and invalidate _every previously issued_ token/session the old-fashioned way, by disavowing the prior signing key, and then bouncing every user/ requiring to re-auth freshly and establish brand new sessions within the totally new PKI?
I assume this is always still possible even with JWT from what I've read so far, but I'm happy to be educated if either of you don't mind sharing.
Not necessarily. Let's say I steal your password and use it against the auth endpoint to get 10 one-time tokens for your account. Re-rolling the master key is a solution, but a very radical one if I can just invalidate all your tokens don't you think? ;)
The tokens are valid, thus there is no objective reason to reject them other than there was an unrelated security failure elsewhere in the system.
Additionally, tokens are generated per request and are short-lived, with an expiration timestamp that is just enough to send a request to the server.
When the token is passed to the server, the nonce is added to the server's scratchpad memory to revoke the token and thus avoid replay attacks. If anyone for some reason wants to revoke a token, they only need to add the token's nonce to the revoked list. If the nonce is present in the list then the server rejects the token and triggers a token refresh.
"It's a common practice to add expiry timestamp for such tokens so each token will expire after certain interval."
With this:
"That's dandy, but it's a solution which is neither standardized nor native to JWT."
People are providing evidence that token expiration is native to JWT to refute that statement, while you are arguing in parallel that "expiry is not revocation" which is related but separate.
If not a service to validate tokens against a blacklist is again trivial and will scale to all but the top 0.1% of organizations. And it only needs to be in the blacklist long enough for the period until the token expires.
Yes, jwt is not ideal. But this talk that you should never ever use them and your service will be immediately hacked etc is silly internet bandwagoning.
For a huge percentage of services jwts are just fine. Anyone reading this, please do not over think this advice and just ship with jwts if that is what you have.
I never said you should never ever use JWT or that your service will be hacked if you do so. In fact, if you kindly reread what I wrote you'll see that I explicitly mentioned there are legitimate use cases for JWT. I am specifically refuting the use of JWT as an authenticated session management system.
> Anyone reading this, please do not over think this advice and just ship with jwts if that is what you have.
This is poor advice.
1) Authentication is sufficiently solved for most workflows and applications that you can use turnkey solutions for more secure and more performant authentication than JWT.
2) What exactly is the scenario you envision in which JWT is all someone has? Do you mean they're forced to use stateless session management, or that JWT is literally all they can do for authentication because nothing else is available?
Good luck using session cookies with Cordova on iOS, for example [1]. In cases like these JWT is perhaps your only option.
So — getting back to the OP — which libraries?
But either way, if you really can't afford a database or cache layer lookup to see if a token is still valid, then you accept that by using a bearer token, that is only validated by signature alone, that it is possible a user will have their session hijacked without possibility of revokation.
The usual way this is mitigated is by use of a small expiry time (I've commonly seen <=5 min) and a revokable refresh token. This still gives a hijacker a possible 5 minutes (assuming 5 minute expiry) if a user revoked the refresh token, but it does mitigate the damage while still reducing DB lookups since you only do a lookup in token refresh. Hope that clears things up. Again your application needs should drive these decisions.
You don't need the ID. You can simply store the token's signature. In fact, some implementations store the whole JWT to avoid roundtrips to the auth service, and revoking the token is just a matter of flipping an attribute in the database.
The token expiry determines the baseline accuracy of banning across all services.
JWT and sessionIds are totally different beasts. JWT are used per request, are designed to expire and be refreshed, are specific to each individual endpoint and store authorization info in a specialized third party service.
In such a system, a user would be logged out after one minute of closing the connection... Probably good enough for online banking. In a way, this is safer than standard sessionId-based auth because once you've issued the token, you don't need to worry about scenarios where the user has gone offline suddenly.
There are very few systems that need banning with down-to-the-millisecond accuracy.
With JWT, you only need to do a single database lookup when the user logs in with their password at the beginning... You don't need to do any other lookup afterwards to reissue the token; just having the old (still valid but soon-to-expire) JWT in memory is enough of a basis to issue a fresh token with an updated expiry.
It scales better because if you have multiple servers, they don't need to share a database/datastore to manage sessionIds.
Also, this is a security consideration because a malicious user could intentionally send fake sessionIds to make us DoS our database. With JWT, verification of the signature only uses CPU on the workers which are easier to scale.
You can steal a JWT token the same way you can steal a session token.
If you can live with quickly expiring, quickly reissued crypto tokens like JWT, it's a boon.
But JWT definitely don't work for web auth. They can be used as CSRF tokens, though.
How will you deal with the usability problem introduced by expiring all sessions for users who are offline (closed tab, spotty internet connection, etc) for at least 50 seconds? It actually seems like you really should be wondering how to interpret users being offline temporarily.
You could just accept this as working as intended, but you don’t need to accept it if you just use normal session IDs. Is your application really so latency sensitive that it can’t tolerate a DB lookup? What is an example workflow in which users on a web or mobile application cannot be tolerably authenticated with standard DB lookups?
You can also use a refresh token, but this brings you back to the revocation problem, but with longer term tokens. Likewise, there is a material difference between millisecond revocation and sub-minute revocation. There are good reasons to care about sub-minute revocation.
Like JWT?
I feel like that argument goes around in circles.
I feel that the problem is that some users are talking about stuff they know nothing about, but still feel compelled to be very vocal and opinionated.
JWTs as bearer tokens aren't bad in their own right, but if you aren't careful you can screw yourself and therefore many security experts avoid them for use in securing systems. Plus a lot of people mistake it for an encrypted token which it isn't. You can imagine how bad that can get.
Tbh I'm with the parent commenter. I avoid them, but if you avoid common pitfalls they should work for your system no problem.
I'm on mobile and can't be arsed to gather sources, but you can search the claims I made and you'll see several articles about these problems. There's even a defcon talk about a new proposed standard (called Paseto I think) that starts by highlighting the major issues with JOSE and JWT specifically.