6

I would like to know the best practices to invalidate JWT without hitting db while changing password/logout.

I have the idea below to handle above 2 cases by hitting the user database. 1.Incase of password changes, I check for password(hashed) stored in the user db 2.Incase of logout, I save last-logout time in user db, hence by comparing the token created time and logout time, I can able to invalidate this case.

But these 2 cases comes at the cost of hitting user db everytime when the user hits the api. Any best practise is appreciated.

3

There's no solution unless you are hitting the DB. You could reduce the number of lookups though to one instead of two.

Upon password change or logout, you write a 128 bit number generated by a CSPRNG to that user's row in your user table.

This CSPRNG forms part of the JWT. On every access you would need to check that the number in the JWT matches the value stored in the DB. There's also no advantage to the MAC being calculated over this value, we are just keeping it in the JWT so everything is in one place.

This sorta defeats the purpose of using JWT in the first place - you might as well simply use a session token that is checked server-side. The advantage though is that you don't need to maintain individual sessions server-side as once a JWT expires it has expired because you won't accept any with expiry dates in the past.

Another disadvantage is that if there are two sessions against the same user, logging out one would logout the other. Also, the logic is more complicated than a server-side managed system, and extra complexity tends to reduce security.

1

You could use a short time-to-live for your JWT tokens and have them renew frequently, with a mechanism to disallow a renewal for older JWT tokens. You'd need an auto-renew-token in the JWT that could be compared to something you store in the DB. This at least means you only hit the database for each renew-cycle. You could set that to 5 minutes, which would be a lot less traffic than every client-to-web transaction.

However, think about it, this is a very high maintenance solution. Only a very small percentage of your users will actually ask to sign-out of all devices.

SUGGESTED SOLUTION:

If you wanted to tell agents not to trust a select few IDs anymore, what would you do? Perhaps you'd ask them to check back with you to update their records for a 'black-list' once in a while. Now you only have a handful of 'stateless' web services checking back every x minutes for an update. You only need to keep a blacklist of the proactively invalidated JWT tokens that have not yet expired.

I think you'll find this solution will scale, and it is usually not necessary to immediately expire a token. Even if you did, you could be too late in making your request to invalidate all tokens, so what difference does 60 seconds make? If you need to perform an action that is so critical (launch the nukes?) - perhaps you should ask your end user to re-authenticate in real-time for that one!

  • suggestion similar to an implementation I did -- poll & cache a blacklist every couple minutes, works great. – Zeb Aug 24 '17 at 20:31
0

JWT best practice is to not use the database or cache at all, the whole idea of JWT is stateless validation check, you can store the user ID within token payload and use it when necessary by several machines without the need to sync a session ID or alike.

Make sure to use long and random user IDs, so if an attacker manages to forge a token, he will only risk one user and will not be able to access other users, unlike sequential IDs.

0

I don't believe there would be any way to invalidate the JWT without checking the database on every request.

The best idea might be to issue access token JWT's with a short expiry time, and then make use of refresh tokens if you need the access token renewed.

This way, although you can't invalidate the token immediately, at least it will only be usable until it expires. When the refresh token is used, your authorization code can then decide if a new access token should be issued, or not.

Just curious though, why would you need to invalidate the JWT just because of a password change? Is there any reason to force a logout at that point? The JWT doesn't include the password, so a changed password shouldn't really have any impact on the JWT.

The only time you should need to invalidate the user is if their permissions have been changed, or revoked.

Logout would usually be a user initiated action, in which case the client can simply clear/reset/delete the JWT token it currently has for the user.

  • 1
    Traditionally when you have logins from multiple devices, say a mobile app and a desktop app, it would be normal to invalidate all sessions when the password is changed. Changing the password invalidates all existing tokens. – RibaldEddie Feb 5 '16 at 3:50
  • If a user fears their password has been compromised, they should change it. This must kill all sessions to be a compete fix. You're idea of eventually killing a session when it expires leaves an attacker access to a hacked account, very bad. – Neil Smithline Mar 28 '16 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.