4

I have a service with a client app (Mac).

To log in, users enter their username and password in the client app, which sends this information to the server.
The server verifies this information using the bcrypted (and randomly salted) hash of the user's password. If successful, it generates a long-lived random 192-bit refresh token, stores it in the server's database, and sends it to the client, which the client stores in the system's keychain.
The client can then use this refresh token to request a short-lived (1 hour) JWT from the server and use that JWT to access the rest of my API.

My question is:

Should I hash the refresh token before storing it in the server's database?

Such hashing would prevent an attacker (who has somehow dumped the DB) from using a refresh token to pose as the corresponding user until the DB leak is detected and all refresh tokens are revoked. Once the leak is detected and all refresh tokens revoked, they would immediately become useless anyway. (Just dumping the DB wouldn't be very useful, as all the actual data is encrypted before being stored in the DB; to exfiltrate a user's information, the attacker would also need to attack the key store or access the service using that user's refresh token.)

And, based on that:

Would in this case hashing the refresh token server-side with "just" SHA256 (for example) be sufficient, or should bcrypt be used for that as well? And, would it be necessary to use a different random salt for each refresh token?

The reasoning behind this is that salting each refresh token individually would necessitate the client to also provide e.g. an UUID for the server to look up the correct refresh token hash in the DB for verification. (Such UUID could simply be encoded alongside the token itself as part of the opaque "refresh token string" provided to the client.) Also, running bcrypt for each client's refresh token/access token swap request could have performance implications.

Remember, refresh tokens are random and thus have no use outside this service nor past their revocation; as opposed to user passwords, they can't e.g. be used to try and log in to another service with the same password. But I might be missing something by not hashing them, so I'd appreciate your expertise on this.

MrMage
  • 151
  • 5
  • Thanks for pointing this out! My question is indeed answered by the linked one; feel free to close this question as a duplicate. – MrMage Jul 09 '18 at 15:13

0 Answers0