linasmnew
linasmnew

Reputation: 3977

How practical would this JWT Implementation be?

Disclaimer, I'm new to JWT's so if any of this makes no sense at all, you now know why lol.

Motivation The security problem this implementation is trying to solve can be summed up by this scenario:

Legit user logs in into the website using a public computer and leaves the place forgetting to logout, attacker sits at that computer, copy pastes token and uses it whenever he likes later when he gets home, (because it will always be valid until the secret changes or if you’re storing token in db until user changes some payload info [what if user never updates info] then token is forever valid).

Authentication flow to sort problems mentioned above

1.   Client logs in
      1.1  Verify login details, and if valid:
      1.2  Create token using user id, global secret and expiry date
      1.3  Store token in Database
      1.4  Send token to client
2.   Client stores token [your choice where u wanna store it]
3.   When client sends a request to an authenticated route, use authentication middleware to do the following checks
      3.1  Verify token hasn’t been tampered with
      3.1.1  If not tampered, go to 3.2
      3.1.2  If tampered, redirect to /login
      3.2  check if expiration date is less than current date
      3.2.1  if not less, let user through to the requested route, by calling next()
      3.2.2  if less, check in database if expired token matches the token stored in database
        (to verify if it’s the latest expired token, or not)
        3.2.2.1 if doesn’t match, redirect to /login
        3.2.2.2 If matches
            3.2.2.2.1 create token with renewed expiration date
            3.2.2.2.2 store token in database
            3.2.2.2.3 send token to client

Security drawback of above implementation In the case where an attacker got access to a token, and is the one that makes the first request post-token-expiration to get a new token, then this would invalidate the legit user when they tried to get new token and log them out as their token wouldn’t match the one stored in database. Now only the attacker would have same token as the one stored in the database.

Ways to mitigate this Invalidate via login or logout: Generate new token on login / delete token on logout, overwriting the old one in db, this would make all previously issued tokens invalid as soon as they expire. i.e. next time attacker would try to get new token on expiration, it wouldn’t match one in db so they would get rejected forever using that token.

Usability problems Logging in or logging out would invalidate token on all other devices, so you would have to re-login on those devices.

Possible work around Have simple request header check for device type and store different token for each device on login and logout. Then have different db queries based on if statement of the different devices when tokens needs to be refreshed, so u know which one to refresh.

Upvotes: 2

Views: 168

Answers (2)

Andreas Lundgren
Andreas Lundgren

Reputation: 12545

I think it looks quite alright, although pedrofb commensta are valid. However consider the option not to store the JWT itself in the DB, but a refresh token instead. The refresh token is not a JWT, it's just a random number, time-stamp or similar, and the refresh token is embedded in the JWT.

Also consider to add a soft expiry on the JWT. The soft expiry is your proprietary expiry. The JWT is valid for as long as the standard expiry date is not passed, but after the soft expiry you would like to validate the refresh-token in the JWT to the once you stored in your DB. That would be the heart beat of how often to actually validate a user to the DB. The standars expiry date on the other hand would be the date where the user needs to interact with your BE at least once in order to issue a new JWT (with a new expiry date). So maybe the expiry date is like 3 months and soft expiry in 5 minutes.

If the user loggs out, changes PW och if you detect odd behaviour, you can invalidate the refresh token in the DB. You can also change your refresh token each time a new JWT is issues to prevent old JWT's to be renewed. Also, you can store a separate refresh token for each device where the user loggs in, just like you planned for your original proposal. (This allow users to log out from individual devide, monitor from what deviced the user is logged in and to log out from a device remotely.)

Upvotes: 0

pedrofb
pedrofb

Reputation: 39241

1.3 Store token in Database

Not necessary and not recommended. Verify signature of JWT is the proof that a JWT is valid. Saving tokens requires unnecessary storage space and database access in each request

Legit user logs in into the website using a public computer and leaves the place forgetting to logout, attacker sits at that computer, copy pastes token and uses it whenever he likes later when he gets home.

This security problem is possible but considers that the risk of attack is low and the number of affected users will not be high because it requires physical access to the shared computer after using your website. Prevention and mitigation measures should be commensurate with the seriousness of the problem.

You have proposed to invalidate old tokens on a new login/logout of the real user, but the user did not logout, so it does not mitigate the risk. The server do not know if the token comes from the real user or from the attacker. Possesion of JWT is the proof-of-authentication.

I suggest the following prevention actions:

  • short expiration time: renew the token every 3-5 minutes

  • Use session storage instead of cookies/localStorage: Session storage is cleared when the browser closes.

If this actions are not enough for you, then consider to request the credentials for login instead of storing the JWT.

The rest of your points are based on storing JWT in database. As I commented above this does not make sense using JWT

Usability problems Logging in or logging out would invalidate token on all other devices, so you would have to re-login on those devices.

Issue a new token for each device. It is recommended to let the token expire, but if you need to invalidate a token, you could use a blacklist including a unique identifier jti in the JWT.

Upvotes: 2

Related Questions