I have a simple question. What is the best way to do a password recovery for a user?
I want the user to be able to click a link like “forget your password?” When clicked, the user will receive an email with a new password.
I think sending the hash is a bad option, then I must generate a random password, convert to a hash + random salt, replace it in the database and send the new random password by email. Is this the best way, or is there another? Simpler is better.
Thanks!
The safest way is to email the person a link to a page that allows them to create a new password. Passwords should only ever be stored as salted hashes. Subverting this process would require that a person’s email be compromised — in which case they’ve probably got worse problems than a compromised password to your webapp.
Files and tables:
I imagine that your database contains a table called “users”, with a column called “userid” which serves as its primary key.
Create a new table in your tabase called
password_resetwith three columns:userid, which is a foreign key pointing to the tableusers;code, which will contain a unique, random number; andtimestamp, which will contain the date that a request is made.Create a page for password resets, like
password_reset_request.php. Ask for a username or email.Create a page for setting a new password, like
set_new_password.php.Logic:
If the username or email supplied to
password_reset_request.phpis valid, insert a row in thepassword_resettable corresponding to the request. Imagine that user Fel has placed a password reset request. Fel‘s internaluseridmight be 564979. The row inpassword_resetwould be something along these lines:564979, 54c4a2767c2f485185ab72cdcf03ab59, 2011-01-01 12:00:00.Send an email to the user’s email address containing an url looking like this:
http://your.url/set_new_password.php?userid=564979&code=54c4a2767c2f485185ab72cdcf03ab59.When
set_new_password.phpgets a hit, it should check for the presence of theuseridandcodeproperties in the URL. Not there? Abort.Sanitize the
useridandcodeproperties if they’re there. This is important.Run an SQL command like this:
SELECT * FROM password_reset pr WHERE pr.userid = $userid AND pr.code = $code AND TIMESTAMPDIFF(DAY, CURTIME(), pr.timestamp) < 1.If you receive no results, Abort.
If you receive a result, allow the user to enter a new password.
After validating the password as you normally would upon registration, use an SQL
UPDATEstatement to change the user’s password.Use SQL to delete any requests for the user from the
password_resettable:DELETE * FROM password_reset WHERE userid = $userid.You’re done!