> For the most simple use case of an client auth state; you want to be able to revoke auth straight away if an account is compromised. This means you have to check the auth database for every request anyway, and you probably could have got whatever else was in the claim there quickly.
FWIW, I built a system previously that got around this "having to check the DB on every access to check for revocations" issue that worked quite well. Two important things to realize:
1. Revocations (or what is usually basically "explicit logout") is actually quite rare in a lot of user application patterns. E.g. for many web apps users very rarely explicitly logout. It's even rarer for mobile apps.
2. You only need to keep around a list of revocations for as long as your token expiry is. For example, if your token expiration is 30 mins, and you expire a user's tokens at noon, by 12:30 PM you can drop that revocation statement, because any tokens affected by that revocation would have expired anyway.
Thus, if you have a relatively short token expiration (say, a half hour), the size of your token expiration list can almost always fit in memory. So what I built:
1. The interface to see if a token has expired is basically "getEarliestTokenIssuedAt(userId: string): Date" - essentially, what is the earliest possible issuance timestamp for a token for a particular user to be considered valid. So, revoking a user's previously issued tokens means just setting this date to Now(), then any token issued before that will be considered invalid.
2. I had a table in postgres that just stored the user ID and earliest valid token date. However, I used postgres' NOTIFY functionality to send a broadcast to all my servers whenever a row was added to this table.
3. My servers then just had what was a local copy of this table, but stored in memory. Again, remember that I could just drop entries that were older than the longest token expiration date, so this could fit in memory.
On the off-chance that somehow the current revocation list couldn't fit in memory, I build something in the system that allowed it to essentially say "memory is full" which would cause it to make a call back to postgres', but again, that situation would naturally clear up after a few minutes if revocations went back down and the token expiration window passed.
This sounds more complicated than it actually was. It has the benefits of:
1. Almost no statefulness, which was great for scalability.
2. Verifying a token could still always be done in memory, at least almost. Over a couple years of running the system I actually never hit a state when the in-memory revocation list got too big.