| ▲ | littlecranky67 7 hours ago |
| In sessions vs. JWT revocation lists, there is an argument in favor of JWT revocation lists. JWTs have a limited expiry timestamp, so you only ever need to maintain a revocation list for tokens not expired yet. Given that you probably only have a fraction of JWTs revoked compare to valid JWTs in circulation, you only need to query a very small dataset for each request. When using sessions, your list of valid sessions is probably orders of magnitudes higher that the revocation list - thus the data lookup costs and the storage cost of that statefulness is higher. Plus, the article mentions JWTs are stateless but that is usually not true. You mostly not only validate the JWT, but also obtain a matching identity object (i.e. user details) for each request to see if the user is still enabled/authorized to do whatever he does. You can leverage stuff such as per-user revocation lists, or a minimum_issued_at that will validate any JWT iat field. This allows the "Logout from all devices" pattern, where that action will simply set a user's minimum_issued_at field to $NOW. All previous tokens will thus be revoked, without individuall revocation list checks. |
|
| ▲ | vidarh 6 hours ago | parent | next [-] |
| The moment you have to look up the user object, you've lost the primary advantage of JWT, and might as well ditch it. |
| |
| ▲ | littlecranky67 6 hours ago | parent | next [-] | | Depends on the system. If you use JWTs for authentication only, they still serve a purpose. Sessions also only serve as authentication, not authorization. Authorization is independent of the both systems, and it depends how you implement that. There are systems where the authorization is done in the JWT too (i.e. scopes/permissions in the token) - in that case you are right. | |
| ▲ | joshmarlow 6 hours ago | parent | prev [-] | | It definitely violates DRY but if you keep passing the JWT down the call chain, you can do redundant permission checking in your business layer. Now the reasonable response to the above is that this should be happening in a dedicated authn/z concern - and that is correct! But when paranoia is called for, it's not unreasonable to have redundant checks in logic where authz is critical. |
|
|
| ▲ | jpalomaki 6 hours ago | parent | prev | next [-] |
| Session data lookup is one select to database that gives 0..1 rows and uses index. In most cases this is not something you need to worry about. |
| |
| ▲ | littlecranky67 6 hours ago | parent | next [-] | | I agree. The storage space, however, is a different story. Your session DB can grow huge, depending on your session lifetime and your users logout behaviour. Plus, it is a concern in a distributed system (i.e. a token can be validated on every node, vs. a session lookup must be globally in sync) | | |
| ▲ | 10000truths 3 hours ago | parent [-] | | 1. For the vast majority of CRUD apps, active sessions will be a very small fraction of the actual storage requirements. A SaaS with 100K MAU may have only 100 or so active users at any given time. 2. Sessions by definition are ephemeral. A database should not be necessary at all, an in-memory cache should suffice. 3. If you really need to distribute session data across multiple nodes, just propagate them asynchronously. Authentication and authorization are semantically idempotent operations. Having to possibly re-auth when making a cross-region request within milliseconds of logging in might be mildly annoying for the user, but consistency isn't a deal breaker here. | | |
| ▲ | littlecranky67 3 hours ago | parent [-] | | > 3. If you really need to distribute session data across multiple nodes What you mean, "if" - you will need that once you are international. You can't afford to verify every http request against a centralized session store when you have users in Australia, US, Europe, Japan etc. You can't beat the speed of light. My point is, replicating revocation lists that are append-only, only a small megabytes, and can be publicly known, is always easier than syncing session databases for a complexity standpoint. |
|
| |
| ▲ | matt-p 6 hours ago | parent | prev | next [-] | | Can even put it in redis too, if you have performance issues from looking for it in memory then you have probably have more users than google. | | |
| ▲ | littlecranky67 6 hours ago | parent [-] | | What if you have two servers, one in japan and one in central europe? Where do the sessions live? With JWTs, you would only need to replicate your revocation list of the last X hours (X being your JWT default lifetime) and probably be in the megabytes for the total list. Easy to replicate that ever 5-10seconds to all your locations. |
| |
| ▲ | mewpmewp2 5 hours ago | parent | prev [-] | | If you have multiple services in multiple locations however, you may want to replicate this data, so in this case revocation list as it's much smaller would be far easier to replicate for much less latency overhead. |
|
|
| ▲ | zsoltkacsandi 6 hours ago | parent | prev [-] |
| > JWTs have a limited expiry timestamp, so you only ever need to maintain a revocation list for tokens not expired yet. Sessions have expiration timestamps too, and you can configure them however you like. |
| |
| ▲ | littlecranky67 6 hours ago | parent [-] | | Yeah of course, but how does that relate to my point? With JWTs you don'T have a list of valid tokens as state, but only a list of invalid ones (revoked). But the list of revoked tokens in the last X hours (where X is your token lifetime) is always going to be smaller than the list of active sessions given a large enough user base. Hence my original point stands, that the lookup and storage costs are lower than on sessions. Whether or not sessions have session lifetimes does not change the fact at all. | | |
| ▲ | zsoltkacsandi 6 hours ago | parent | next [-] | | > With JWTs you don'T have a list of valid tokens as state, but only a list of invalid ones (revoked). Yes, and a lookup operation is a lookup operation. Your database or data structure used for storing the sessions/JWT revocation entries won't really care whether you look for things that are active or things that are inactive/revoked. If you store it in the right database, both lookups will be O(1), so it is the same (or at least the difference is negligible), regardless of the size. | | |
| ▲ | littlecranky67 6 hours ago | parent [-] | | The story changes if you have a distributed database. replicating a smaller revocation list (that is append only) that will never be more than a couple of MB, is easier to do accross distributed nodes around the world than keeping a larger, session state db replicated. Heck, your revocation list can even be public (it contains only a list of substring of a few bytes of hashes). Syncing sessins can be done, no question, I would just think JWT+revocation db is easier to implement, yet robust. | | |
| ▲ | conradludgate 4 hours ago | parent [-] | | It can also be encoded as a bloom filter for very fast checks. Then you can defer to the replicated LSMTree that's stored replicated on your local node |
|
| |
| ▲ | doctorpangloss 6 hours ago | parent | prev [-] | | isn't it that you must have a revocation list in many cases? if you cannot get from N to 1 or 1 to 0 states, if you're just going from N to N-1>1, you haven't materially decreased your statefulness | | |
| ▲ | littlecranky67 6 hours ago | parent [-] | | But the revokation list is always going to be orders of magnitude smaller than the list of active sessions. | | |
| ▲ | doctorpangloss 5 hours ago | parent [-] | | that may be, but who cares how big or small it is really if you are facebook sized, with 1b+ active sessions versus an alternative with 10m+ revocations... the kind of applications that reach this scale, they have enormous amounts of state anyway. | | |
| ▲ | littlecranky67 5 hours ago | parent [-] | | Everybody thinks Mag7 scale, but actually it is more relevant if you are a tiny webservice - but available world wide. If you need to match each and every http request from a user half way around the world against a central db, you can't beat the speed of light. If you can do authentication on each downstream server directly using crypto and JWT validation, you at least save that roundtrip to the session db. The revocation list is tiny (a few megabytes tops), append-only, can be public to the world, and thus easy to replicate to your downstream nodes. If you are a smaller gig, you won't have to bother with replicating your sessions and keeping them in sync globally. |
|
|
|
|
|