Do not use uniqid()
as a random value in any security-critical code. This includes password resets — an attacker may be able to predict the value of uniqid()
, permitting them to guess a security token and reset the password of any user on your system.
Instead, use bin2hex(openssl_random_pseudo_bytes(…))
(as seen in your question) to create a secure random token. The PHP manual specifically recommends this function for the purpose in a footnote to the entry on uniqid()
:
This function [that is, uniqid()
] does not generate cryptographically secure tokens, in fact without being passed any additional parameters the return value is little different from microtime(). If you need to generate cryptographically secure tokens use openssl_random_pseudo_bytes()
.
As the result of bin2hex()
is a printable string, you can store it in your database using any string type. VARCHAR
should be your default choice here, and it's perfectly appropriate.
For maximum security, you may want to take one additional step. Instead of storing the token in the database, store a hash of the token (e.g, sha1($token)
) in the database, then compare the hash of the value presented by the user with the stored hash. In essence, treat it like a password! This extra step will prevent an attacker that has the ability to read your database, but not to write to it, from gaining control over a user's account by reading their "forgot password" token from the database.