auth0 / node-jsonwebtoken

JsonWebToken implementation for node.js http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html
MIT License
17.75k stars 1.23k forks source link

How to forcefully invalidate a token .. on logout #375

Closed webrocom closed 7 years ago

webrocom commented 7 years ago

Hi How can i invalidate a jwtoken forcefully when i call logout.

ziluvatar commented 7 years ago

Not sure what's your use case, JWT as session token, JWT as access token, JWT as id token, etc

Client: remove saved tokens.

Server: You would need to use another piece of information stored in your backend, so that when the token is used you can double check for that. ie: check for jti stored (you could only store it at the logout moment if you will)? check for session cookie and ignore any JWT if it is not present?

Short lived tokens would minimize the problem as well.

iBicha commented 7 years ago

Use a place to store "blacklisted tokens" and add a search in it in your verification flow (if token is verified, check if you didn't blacklist it) also on logout, add the token to the blacklist. This allows you to easily clean up the tokens after the actually expire (run a job every few days maybe)

webrocom commented 7 years ago

@ziluvatar its JWT access token.

Like in php JWT token we have a method token invalidate .

So how can i invalid a jw access token in sails js, which i received at login in time

ionull commented 7 years ago

Yap, one should be able to remove token when logout, and even remove all tokens when reset password. Check guardian and guardian db project for Elixir.

tim-phillips commented 7 years ago

As @iBicha mentioned, you can blacklist a JWT. This is typically done by creating a JWT ID (jti claim), storing it, and making sure that it is never used again.

The jti (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well. The jti claim can be used to prevent the JWT from being replayed. The jti value is a case-sensitive string. Use of this claim is OPTIONAL.

http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#rfc.section.4.1.7

If you wanted to not store every blacklisted JWT ID, then you could generate those algorithmically and reject them en masse. If your IDs were incremental (a very simple and not necessarily recommended case) you could reject any IDs less than a certain number.

ziluvatar commented 7 years ago

@webrocom you got some good responses, if I have to add something I'd say: If your resource servers (APIs) will check to db (or another service) whether or not the access token is blacklisted on every request, I'd go for opaque tokens since you probably won't get any benefit from JWT access token format.

webrocom commented 7 years ago

@ziluvatar Exactly that would be not beneficial . I think i can use refresh jwt token on logout api. Is it good ??

ziluvatar commented 7 years ago

JWT benefit is, among others, to have a token that different parties can use as long as they trust on the issuer, where there is no need for them to interact with the issuer service (maybe minor interaction to download public key), they can verify it and use the information the issuer provided.

If any service that will use the token will have to interact with the issuer to know if it's valid, why bothering about managing JWTs (signing, verification, keys management, etc), of course, you can still use JWTs but then you have some challenges like the one you are asking for.

I think i can use refresh jwt token on logout api. Is it good ??

Sorry, can you elaborate?

corysimmons commented 7 years ago

@webrocom https://stackoverflow.com/questions/21978658/invalidating-json-web-tokens there are a bunch of strategies for this.

ozanmuyes commented 6 years ago

Blacklisting the token (or it's ID - jti) is probably less secure than whitelisting them. It's good to know which ones are valid instead of which ones are not. This approach has two benefits, if (somehow) the underlying software/server (let's say it's Redis) crashes then every token can pass because you are only disallow a token if there is a matching record on the cache (Redis in this manner). If you've only allow the ones which has corresponding record on the cache it would then pass. In the case of crash non can pass, so users have to login again, on the other hand with the blacklisting approach everyone can pass. The 2nd benefit is that you only need to have records for valid (not expired) tokens, not every token that had been created and then expired due to age. It helps you to keep the cache size smaller. Also if the cache supports lifetime for keys (as Redis does) you wouldn't need to manually scan and delete records for the expired token on the cache.

(Update) tl;dr

(Update) Logging the user out is merely an effort to remove the whitelisted key from the cache.

iBicha commented 6 years ago

If you keep allowed tokens (whitelisting), then you don't need JWT, you just store a random token and check against it. But in a real world scenario, the number of blacklisted tokens is way less than the valid ones (people don't log out as often). And blacklisted should be persisted and flushed often (removing the ones that expired, because they wouldn't pass the JWT verification) which means the search space in the blacklisted tokens would be always small.

ozanmuyes commented 6 years ago

@iBicha Yes you are right, but that brings us to the question "Should I be using sessions or build my server following the stateless architecture?" I think. Since JWTs are self-contained their usage differ from (let's say) cookies - sessions. And since black-/whitelisting requires us to store some kind of data about the token in question, I suggest that this data will be used to allow it to pass (again, instead of disallowing). Storing piece of data about the token isn't against the stateless architecture, but storing whole data on the server-side and sending the identifier to the client is. The data I've been mentioning about, by the way, is not a random data, contrary, it has link to the token. I advice it to be the 'jti' of the token. On the other hand any other piece of data or custom claim might be key for the cache entry.

fatso83 commented 6 years ago

There are so many misconceptions about JWTs here ... JWTs can be perfectly good, but there are so many of the responses above that shows that it is being used where an old-school session mechanism would be much more suitable. Peeps should read up on why JWTs shouldn't be used for sessions.

akhilkc-rcggs commented 5 years ago

https://medium.com/devgorilla/how-to-log-out-when-using-jwt-a8c7823e8a6

travis-infosec commented 5 years ago

https://github.com/sirwolfgang/jwt_keeper

phalconVee commented 5 years ago

To forcefully invalidate a token upon logout on the server side, try

$token = $request->header('Authorization');
JWTAuth::parseToken()->invalidate($token);

The above will set the token to blacklisted.