11 ms·
That last part where he talks about logging out being the responsibility of the client is rather key. Basically I can't invalidate the key from the server side.
by nstart 10y ago
That last part where he talks about logging out being the responsibility of the client is rather key. Basically I can't invalidate the key from the server side. So if a user's account is compromised and they recover it on their mobile app for example, I can't sign the user out of everywhere else too. It's what has given me pause about jwt so far and has held me back from using it. I find the cookie is generally good enough to hold most other information I need about the user.
- aleem 10y agoThe impact can be mitigated by having low TTLs and using refresh tokens. This will give you a rolling window. If the TTL is 10 minutes and the client doesn't make any requests in 10 minutes, they will be timed out. But if the client continues to have at least one request every 10 minutes the session persist. Session persistence can also be ensured by having your web-client for example make a request to the server every couple of minutes. Server-side key invalidation is entirely possible but it would require having a blacklist of disabled keys and comparing every requests against the black list. This would obviously concede the benefits of scale from JWT tokens since you are doing the same thing as server side sessions. However, the black list should be considered only as an escape hatch and need not be enabled at all times. In fact, once all the tokens in the black list expire, the black list itself can be disabled and things go back to the way they were.
- btdiehr 10y agoWhy do you think you can't invalidate a JWT? Store a JWT that is associated with some object in a database that has the field `isInvalidated`. This isn't rocket science. Sure - this turns the JWT token into a session but there is no way to invalidate based on something that isn't determined at creation time without storing something in a database.
- jontro 10y agoWhat's the point of using a JWT if so? This effectively converts it into a session token
- baseonmars 10y agoYou can create a JWT without writing to a datastore - this is a key difference.
- kensign 10y agouse a ttl on like a cache store, such as redis
- jcoffland 10y agoYes, but this is still a deadend.
- zbjornson 10y agoHow so? It's effectively a micro-optimization that will have no real effect, but you can do a simple "exists" query when searching the revocation list, and the TTL keeps the collection small. Not advocating for JWT as it's a silly mess to do everything correctly, but it is possible.
- jcoffland 10y agoSearching a revocation list misses the point of RESTful authentication.
- bigonlogn 10y agoYou can implement sign out everywhere by setting a reauth flag on the user in the database. You lose the "completely stateless" aspect that JWT claims to provide, but it's a small trade-off for tighter security.
- nneonneo 10y agoIf the user reauthenticates and you unset the reauth flag, wouldn't their previous sessions (e.g. tokens held by an attacker) suddenly become valid again? How would you prevent such an attack?
- inopinatus 10y agoYou wouldn't use a boolean flag. I suggest setting a validity timestamp for the user, and reject any token that was issued-at any earlier time. (This isn't a perfect scheme since a compromised issuer could have been induced to send post-dated tokens. If your need for global logout was to invalidate tokens issued by a compromised issuer, you'll need to blacklist keys as well)
- tszming 10y agoEffectively now you are using database as your session storage?
- dexterdog 10y agoBut you're not storing the session there, just the key/token so you can change it. The session payload is still completely in the JSON body maintained by the client and sent with each request.
- jeremyjh 10y agoWhat difference does that make? Once you commit to this you have to do a database lookup for every request. Why not keep the session data there?
- jcoffland 10y agoThis is exactly right. Many people confuse this problem with solutions that involve storing state on the server. Doing so completely misses the whole point of RESTful authentication.
- tjbiddle 10y agoI store a `login_count` in my User model. When searching for a user I `find_by_user_and_login_count`. The token they have has their current login_count in the claims. If I want to logout server side, I just update this value (Can be a random string if you'd rather it not be in increasing integer) and it will invalidate all tokens. When they logout client side, of course we can just clear the token from their memory. If they want to invalidate all tokens, then we have an API endpoint for that and it will logout from all devices.