Because JSON Web Tokens are short-lived, the blacklist need only contain tokens valid for validity period plus a few seconds and remains very small (often empty).
If you use JWT to allow authorization on several server, then you do need to distribute this blacklist, so it is not a completely trivial solution. In the simplest scenario you might suffice with only maintaining a blacklist on the server that can refresh tokens (this means that when the token expires, a new one cannot be automatically acquired).
Now, you (probably) only absorb the DB hit on blacklisted tokens.
1. As other posters pointed out. The blacklist is probably pretty small and can live in memory on your apps servers. If you have a distributed raft network or something to keep it in sync across nodes, even better.
2. You can avoid checking it against the DB unless the API call is sensitive (example: modifies data).
Oh, and also: "only store a blacklist" does not work if you want to provide the "revoke this app you gave access to a while ago and now it's spamming" functionality like in most social networks.
For me, the log out / cross device session management issue seems to force a pattern of short expiry with self refreshing tokens. Commonly used devices feel always logged in, whereas uncommonly used devices end up needing a fresh log in each time.
0: https://www.chosenplaintext.ca/2015/03/31/jwt-algorithm-conf...
For example -
If some critical part of your app depends on a user's account or session being still valid, just do the check on that endpoint call (grab the sub/ID claim from the JWT and hit the DB, or similar).
The rest of the time - viewing stats/feed/whatever, admit that if the user had a valid token issued to them 5 minutes ago, it's probably OK to send them stats without having to check revocation (or whichever benefit of JWT you're exploiting).
Thing is, this at least gives you the /option/..
JWT tokens have the expiration date embedded in the token. There is no way to force it to expire like you you can with cookies.
Although force is a strong word. Even with cookies if you tell the client to delete a cookie it doesn't mean it has to listen.
In most of our implementations we achieve this by differentiating between the session token and a request token. Requests that actually power the app use tokens that are very short lived. Request tokens are generated by the core auth server using the session token. A session can be invalidated at the core auth server which will then refuse to give request tokens to the bearer.
As long as the problem is known to the developers and the key is specified, I think the biggest issue of JWT is the lack of session invalidation (that is, if you log out your already emitted tokens are still valid until their expiration), but it's a good tradeoff for not having server sessions.