Any best practice on how a reset password token should be constructed? I'm thinking:
random 17 characters [a-zA-Z0-9] + a globally unique id + random 17 characters [a-zA-Z0-9].
Is there a better solution, or an industry standard on reset password tokens?
There are some important points to consider.
- The code should be really random (read from MCRYPT_DEV_URANDOM), and should not be derrived from other user related information.
- Ideally the code is base62 encoded (A-Z a-z 0-9) to avoid problems with the Url.
- Store only a hash of the token in the database, otherwise an attacker with read access to the database can reset any account.
This leads to the problem that you have to find the hash of the token in the database, after the user clicked the link. There are two possible ways to store the token:
- You hash the token with a hash algorithm like SHA512 without a salt. This is secure if the token is very strong (minimum length 20 with 0-9 a-z A-Z). Theoretically you have to check whether such a hash already exists before you enter it in the database, in practise this is negligible. I implemented a password-reset class that can handle such tokens.
- You hash the token with BCrypt and salt. This allows for shorter tokens, but you cannot search for the hashed token in the database. Instead you have to include a row-id in the link to find the token.