4 ms·
I feel like the argument against #2 is usually purely hypothetical in nature. I really do not have a problem maintaining a small lookup cache for revocations. I
by meddlepal 10y ago
I feel like the argument against #2 is usually purely hypothetical in nature. I really do not have a problem maintaining a small lookup cache for revocations. I feel like the argument against doing this tries to take the form of all server-side kept state is bad when in reality it's sticky state and huge object graphs (read: memory consumption) that get stuffed into session objects that are the real evil.
A server with 1GB can hold a lot of JWT's in memory. Probably more than most of the people building services here have to actually deal with.
- falcolas 10y agoSure, revocation lists are relatively small. But they need to be available to every server (replication), be proof against server/service restarts (durable), and checked with every request (highly performant). So, a good revocation list effectively requires a database. Not a trivial thing to implement yourself, and a weighty requirement for an otherwise stateless service.
- justinclift 10y agoHmmm, using a database (eg PG) for the authoritative information, with memcached in front sounds like it would be practical for most uses.
- falcolas 10y agoAt which point you should probably ask yourself: "What value is keeping all of my state inside this token providing me?"
- mwpmaybe 10y agoProbably not. If the Pg instance is replicated, as indicated above, it'll be challenging to keep the Memcached copy in sync. In other words, you can't just use the caching feature of your ORM, you'll need another piece.
- justinclift 10y agoThanks, that does need further thinking about. :)
- deleted 10y ago[deleted]
- cygned 10y agoPostgres is not a good solution for this kind of data. I'd use Redis, but maybe there are even better products.
- Chris2048 10y agoCould you just have per-server tokens? Wouldn't a single client tend to hit just one server anyway?
- dkersten 10y agoWouldn't a single client tend to hit just one server anyway? No? Maybe? It depends on your load balancer. Assigning a client to a specific server is "sticky sessions". Many of us don't want to tie a client to a specific server and prefer a completely stateless 12-factor-style mechanism where any server can serve the client and stateless tokens provide a mechanism to achieve this.
- tracker1 10y agoNot to mention the challenges with multi-region replication needs... to do this for every request along a server-server pipeline adds more latency still, since each request to the db means potentially 2-3ms on top of more complex requests, which all adds up.
- Chris2048 10y ago> and stateless tokens provide a mechanism to achieve this without revocation. What's wrong with tieing a client to a server, or co-located server? Either they are close enough to share tokens / sync fast, or not?
- dkersten 10y agoWhat's wrong with tieing a client to a server, or co-located server? Nothing, if you can get away with it. What do you do if your server dies or is overloaded? The 12-factor patterns came to be for services running on ephemeral hosts in cloud environments. Stateless servers mean you can seamlessly serve requests from another server without problem. Sure, you can store the sessions in a shared resource (redis perhaps?) but this complicated failover and redundancy and may add latency. Maybe this isn't an issue, maybe it is. If you don't need or want that, then just use normal sessions, for sure. Revocation can be handled (although admittedly not as well as with sessions or stored tokens) through short TTL's and refresh tokens (which are stored, but only need to be looked up when the stateless token expires). Its not perfect, but its often a good enough tradeoff.
- unscaled 10y agoJWT are even smaller than their size since you can revoke them by hash (although you should really just revoke by user ID in most cases). Your tokens should generally have a rather short lifetime - then you can keep the entire relevant window of revocations in memory. The implementation is not trivial though, that's for sure.
- elithrar 10y agoIf you go so far as to maintain a revocation store that is checked on each request, you might as well just use that same store for full-blown server-side sessions. By your measure, 1GB can store a lot of tokens in memory: 32B tokens + that again as metadata (e.g. user ID + TTL in Redis) = 15,625,000 tokens.
- infogulch 10y agoNo, the session state itself may be orders of magnitude larger than an id. At 4 bytes per token you can store up to 250M ids per 1 GB. But session state might store kilobytes of data per user for roles, permissions, names, descriptions, links etc. And you're overestimating the necessary size of a revocation store. Only a tiny fraction of your users ever log out or otherwise invalidate session via means other than TTL. You're looking at storing just a couple thousand 4-8 byte revoked session ids and ttls instead of gigabytes of session data. If you have a security breach and need to invalidate all tokens, just reject all tokens with an issue date before it's fixed. And they all fall off anyway after a week (or however long the ttl is).
- tracker1 10y agoOr better, have a really short lived requirement for server-server jwts (I suggest even 1m, having a new one per request). For client-server a 5 minute refresh is fine, as long as you do a lookup for refresh, so you can expire refresh tokens, requiring a full re-auth.