19

I plan on using JWT for my login system for mobile devices. There is no real standard workflow for refreshing JWT tokens I could find so I created this one below. The reason I want to use JWT is for performance reasons. Instead of checking if a user is valid with a database call for every single request I trust the JWT.

I have the proposed workflow which I want to implement into my app. Is this acceptablly secure? Efficient? Are there any obvious problems I am overseeing? What reasonable improvments can be made?

User logs in

  1. If no HMAC signed token exists inside of localstorage, the user gives a name to the device.
  2. DeviceName gets sent to the server where it is inserted into database.
  3. JWT token + HMAC signed token of the DeviceName are sent back to user. The HMAC signed token is put in place to make sure the jwt token (containing DeviceName) is sent from the same device that called it originally.
  4. JWT token is valid for X hours so a user can make any calls for X hours.
  5. After X hours, the JWT is expired. When a request is made the server can see the JWT is expired. Server will now attempt to refresh the JWT token. Server checks the database to see if the DeviceName specified in the HMAC signed token is the same as a valid device name in the database for that user.
  6. If so, create new JWT valid for another X hours, if no, send back message to require login.

If an account is compromised:

User can log into my password service. Once logged in, I would retrieve all the devices for that user, the user can then revoke their compromised device. Once this is done, a request to refresh the JWT will not work with the stolen token.

All of this of course happens over SSL.

My concerns which I have no solutions for:

  • If a JWT token is stolen the attacker has X hours to make calls based on the victim. I think this is the nature of tokens though and an accepted risk?

  • If the JWT is stolen, that means there is a good chance the HMAC token containing the device name is also hijacked so the user could refresh tokens until the victim realizes their account is compromised and revokes access. Is this accepted practice?

Jens Erat
  • 23,446
  • 12
  • 72
  • 96
user2924127
  • 877
  • 1
  • 8
  • 17

2 Answers2

20

Acceptably secure within the realm of what?

You have described the basic flow for all bearer tokens. They who bear the token have the power. You do have a condition where you check if the token has been revoked, but that will mean the token is valid until they expire or are revoked. This is fundamentally the same as checking if the user is valid in the database, but you're replacing user with device + JWT. That's fine, but it's not much of a performance gain.

Other systems use two JWT's (or a JWT and an opaque token). The first JWT is your access token used mostly like you describe, but you don't check for revocation. This token is very short-lived -- maybe 20 min -> 1h, and then you have your refresh token which lives considerably longer. When your access token expires you send the refresh token and if the refresh token is still valid you issue a new access token. If the refresh token is expired you can force authentication again, or just issue a new access and refresh token.

The value here is that you only need to validate the refresh token against the database, and you only need to do that when the access token expires. When the user marks the refresh token as revoked then the refresh token doesn't get the attacker a new access token.

The trade off is that you don't query into the database as often, but the attacker can do whatever they want as long as the access token is valid. This is mitigated with using a very short lived token (its a game of odds). Whether this is an accepted risk is totally up to you. We don't dictate whether you should accept the risk. :)

Steve
  • 15,155
  • 3
  • 37
  • 66
  • Thanks for the reply! Sorry for the dumb question, but what is an opaque token? – user2924127 Jun 09 '15 at 17:10
  • Opaque in this context just means whatever you want it to be, so long as its safe for session use. Could be a random string or whatever you want. – Steve Jun 09 '15 at 19:35
  • 1
    What sort of attacks do short-lived tokens mitigate? Naively, as a noob, I'm thinking if the attacker has your `access_token`, he probably has your `refresh_token` as well. But I guess in this case, you're screwed either way and have to revoke the `refresh_token`. – user1164937 Aug 14 '16 at 16:16
  • @user1164937 it only changes how long an attacker can use an access token *once the refresh token has been revoked*. It has no effect if you don't revoke the refresh token. – Steve Aug 15 '16 at 13:52
-1

Security is always relative and with more efforts we can make it one step harder for anyone to abuse the system. The bearer tokens are IO bound (cache/database call) and JWT tokens are CPU(encryption/decryption) bound. Both are good enough solution to in regular services world except for one thing that we are taking about mobile devices here. One of the approaches that could be used here is to send the token/refresh token to the device through backchannel instead of sending it as a part of authentication. Seems somewhat extra work but gives somewhat more security around issuing and refreshing the tokens for mobile devices. More details can be found here http://sdhankar.com/2016/10/24/authentication-and-jwt-token-refresh-on-mobile-devices/