0

I'm working on an API using Node and Express, with a Mongo database. My users can authenticate using a route, and they get a JWT in exchange.

I want to implement a security mechanism to protect said tokens. Namely, I want the tokens to auto-revoke when a user changes their password, and provide a "Revoke all apps" button, that would invalide all created tokens.

To do so, I added a nonce in the JWT body, which is a random v4 UUID. When the user changes their password or click the button, a new UUID is generated, causing a de-facto revocation of all tokens - since the JWT's body won't match what's coming from the database.

Is this a good approach? I can't think of a way this would be broken, is there anything I overlooked?

Anders
  • 64,406
  • 24
  • 178
  • 215
Rogue
  • 131
  • 2

2 Answers2

2

Your approach is sound when it comes to security, as long as you (1) use a cryptographically secure PRNG, and (2) don't leak the UUID's somehow. However, it does mean that you have to hit the database to check the UUID at every request. That negates the performance boost you get from using a JWT instead of a traditional session ID.

A minor performance tweak you can do is to instead add revoked tokens to a revocation list that is automatically pruned to remove expired tokens. At every request, you check if the token is in that list. Since a list of all revoked tokens is likely to be shorter than a list of all your users, lookup would be somewhat faster.

And as always the devil is in the details. I am sure there are plenty of mistakes one could make while implementing any of these schemes in code, but that level of detail is beyond the scope of your question.

Anders
  • 64,406
  • 24
  • 178
  • 215
  • All right. The PRNG used in my uuid package was audited apparently (which is amazing when you consider it's a free npm package), so i'm good in that regard. I will give your idea a shot, sounds like it would indeed be faster. Thanks ;) – Rogue Mar 02 '17 at 12:51
  • I just want to implement it, but the blacklisting does not work for me. If user just want to logout of all sessions, I am not able to find all historical valid tokens unless I got complete list of tokens (whitelisting). – Tomas Kubes Jan 14 '22 at 06:54
0

As Anders said, you will need to hit database on every request. Along with an optimization he is proposing with a list without expired tokens, you could implement that list as a bloom filter in memory. That way you will need to hit the database only in case of "Maybe" answer and the performance would be much greater.

Marko Vodopija
  • 1,062
  • 1
  • 8
  • 19
  • This is not an answer to the question. – Sjoerd Mar 02 '17 at 13:49
  • A proper answer to a question was given by Anders. I wanted to add yet another method how to improve performance even more. Since I can't comment, the only way I could do that is by adding a new answer. I upvoted his answer to be above mine for clarity. The idea is to share knowledge and help others. Don't understand the need to downvote mine but if it makes you happy... – Marko Vodopija Mar 02 '17 at 13:57