Best Practice to Generate Random Token for Forgot Password

best practice to generate random token for forgot password

In PHP, use random_bytes(). Reason: your are seeking the way to get a password reminder token, and, if it is a one-time login credentials, then you actually have a data to protect (which is - whole user account)

So, the code will be as follows:

//$length = 78 etc
$token = bin2hex(random_bytes($length));

Update: previous versions of this answer was referring to uniqid() and that is incorrect if there is a matter of security and not only uniqueness. uniqid() is essentially just microtime() with some encoding. There are simple ways to get accurate predictions of the microtime() on your server. An attacker can issue a password reset request and then try through a couple of likely tokens. This is also possible if more_entropy is used, as the additional entropy is similarly weak. Thanks to @NikiC and @ScottArciszewski for pointing this out.

For more details see

  • http://phpsecurity.readthedocs.org/en/latest/Insufficient-Entropy-For-Random-Values.html

Best practice on generating reset password tokens

There are some important points to consider.

  1. The code should be really random (read from MCRYPT_DEV_URANDOM), and should not be derrived from other user related information.
  2. Ideally the code is base62 encoded (A-Z a-z 0-9) to avoid problems with the Url.
  3. 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.

Implement password recovery best practice

First off, do not store a plain-text copy of the user's password, or even an encrypted version. You want to only ever keep a hashed copy of the user's password.

As for recover solutions, I find that the recovery link to change the user's password is the best solution in my experience. It will probably be a bit more convenient for the user, while being largely the same from a security point of view as sending a new random password to be changed after next login. I'd still recommend having the recovery url expire after a reasonable short period of time, as well as only being usable a single time.

what is the best way to generate a reset token in python?

Not sure it's the best way, but I'd probably just generate a UUID4, which can be used in a URL to reset the password and expire it after 'n' amount of time.

>>> import uuid
>>> uuid.uuid4().hex
'8c05904f0051419283d1024fc5ce1a59'

You could use something like http://redis.io to hold that key, with a value of the appropriate user ID and set its time to live. So, when something comes in from http://example.com/password-reset/8c05904f0051419283d1024fc5ce1a59 it looks to see if it's valid and if so then allows changes to set a new password.

If you did want a "validation pin", then store along with the token, a small random key, eg:

>>> from string import digits
>>> from random import choice
>>> ''.join(choice(digits) for i in xrange(4))
'2545'

And request that be entered on the reset link.

best practice to generate random token for forgot password

In PHP, use random_bytes(). Reason: your are seeking the way to get a password reminder token, and, if it is a one-time login credentials, then you actually have a data to protect (which is - whole user account)

So, the code will be as follows:

//$length = 78 etc
$token = bin2hex(random_bytes($length));

Update: previous versions of this answer was referring to uniqid() and that is incorrect if there is a matter of security and not only uniqueness. uniqid() is essentially just microtime() with some encoding. There are simple ways to get accurate predictions of the microtime() on your server. An attacker can issue a password reset request and then try through a couple of likely tokens. This is also possible if more_entropy is used, as the additional entropy is similarly weak. Thanks to @NikiC and @ScottArciszewski for pointing this out.

For more details see

  • http://phpsecurity.readthedocs.org/en/latest/Insufficient-Entropy-For-Random-Values.html

Php, is password reset token without database secure?

I would argue the approach linked is "not secure".

The code uses a hand-rolled approach in an attempt to verify the integrity of the URL/token data. The idea is that only the server (which should be the only entity that knows the user password and salt) can generate the given SHA1; on receiving the URL the SHA1 can be regenerated and, if it matches, then the solution proposes that the URL "must" have been server generated and can therefor be trusted.

However, the above assumption might be violated! If the bcrypted/hashed passwords are already known1 then the attacker can generate arbitrary reset URLs and gain access. This is because the attacker has all the required information to forge his own "verifiable" URL.

Applying encryption - after the token generation, to avoid exposing information as Blender pointed out, perhaps - or using an HMAC would increase the knowledge required as an extra "server secret" is used to generate such reset URLs. Encryption and MAC validation is employed in cases where confidentiality and integrity checks of client-stored-and-returned data are performed2.

However, if this additional "server secret" was learned by the attacker, then same issue as mentioned above would still hold and fake reset URLs could be generated at will. (But at this point I suspect that there be other security holes that are more pressing ..)


As far as bcrypt vs. SHA1: there is no point to switch due to the huge input space - the password should already be hashed at this point! - and limited timeout of reset requests. So switching to bcrypt here adds no extra security and using bcrypt does not mitigate the previous issue mentioned. (On the other hand, SHA1 is a poor choice for the actual hashed passwords!)


1 While it would be nice if account/password information is never leaked, the very point of password hashing to begin with is to prevent [mass] exploitation should such a leak occur. Because such leaks are thus taken as a "could happen" scenario (and they do happen), then additional security measures should already assume that such account/password information may not be used as a secure secret.

2 ASP.NET ViewState secuity/validation supports both encryption and integrity verification which shows, that with a solid implementation and security precautions, database/storage-less approaches can work in secure enterprise environments.



Related Topics



Leave a reply



Submit