My point is, you always have state. If you care about that state being anything but _the current time_ (e.g. just letting tokens expire and not worrying about revocation), you need shared storage.
I see clearly why some small subset of applications benefits from carefully minimizing shared state among components. It is not at all clear to me why pseudo-statelessness is a good default.
The point is that it's easier for distributed systems as a whole when clients hold onto their client-specific state, rather than a minimal token that the server, likely being load balanced for availability, must exchange for that state with yet another service in yet another stateful/authenticated request/response manner.
Isn’t that state? If you add state to something stateless you are generally on your own.
[edit: also I disagree with the notion that something with an expiration date is stateless. It has two states. It’s just that the look like idenpotence]
Why is that scenario relevant if tokens are supposed to be used once per request and short-lived?
Once a token is used, it's supposed to be expired and no longer in use. Both the expiry timestamp and the nonce fields already handle those use cases.
Previous person mentioned logout, so I assumed we were talking about session tokens--which I understand its a misuse of JWTs--and is why he/she's mentioning it.
But if we're talking about just one time auth tokens, then yeah, you don't need expiry ahead of the expiry time, and it's plain it's a non-issue.
I don't agree. The expiration timestamp is not a state, nor is a nonce/token id. Moreover the specs enable servers to arbitrarily reject tokens, which means servers can arbitrarily request token refreshes. This means that any argument regarding how a nonce is a state is entirely irrelevant and without any practical interest.
You've misread what I've said. The server can trigger token refreshes by rejecting the request. According to the JWT workflow, that triggers the client to request a new token and retry the request.
> The question here is which token to reject.
That isn't much of a question, because servers are free to reject any token arbitrarily. They can, however, ignore specific tokens that cease to be valid, such as expired tokens or tokens which have already been used. None of those scenarios involves any change to the token's state.
1) A token gets compromised.
2) You know which token. You need to revoke access.
3) You introduce state by storing said token on disk / in memory somewhere.
Key takeaways:
1) The authentication system (not the token) is now stateful. 2) You now have to check this data store to properly allow authentication. 3) A core benefit of JWT (stateless auth) is gone.
Tokens are single-use and short-lived. Once a token is used it's revoked.
> 2) You know which token. You need to revoke access. > 3) You introduce state by storing said token on disk / in memory somewhere.
You don't. You simply reject the token and let the client refresh its token. That's it. There is no state. Compliant clients already expect tokens to be rejected for no apparent reason. They are access tokens.
Why exactly are you assuming that an access token is not single-use or even short-lived, particularly in bearer token protocols specifically designed so that tokens are ephemeral and single-use?
> 1) The authentication system (not the token) is now stateful.
Even if you shoehorn your definition of statefulness, that's entirely irrelevant. The whole point of an authentication system is, following your line of reasoning, to implement a stateful system. Thus, not only is that line of reasoning absurd, it also completely misses the point of implementing an authentication system, not to mention it ignores a whole class of attacks. And for what, exactly?
Instead of an "active sessions" table you could just maintain a list of revoked sessions and check each incoming request against that list. You can make revocations expire shortly after the JWT was set to expire.