I'm trying to figure out best practices for working with password reset tokens.

Say a user initiates the password reset process and the are emailed the reset token and we store a hashed copy in the database. The token is time stamped in our DB and will be considered expired in, say, 24 hours.

Now consider two scenarios for what could happen next:

1) The user thinks he didn't get the email, tries to reset again. Should we allow him to generate another token? If we do, should we delete the old token immediately? (They all will be invalid from 24 hours after the issue datetime anyway...) I think it would minimize support calls if we allow a little flexibility as long as they're expiring anyway. Is there an attack type I'm not considering here?

2) The user received the email and clicks the reset link but doesn't complete the reset form. When should I delete the reset token? Only after a successful reset--the user can click the link again and again during the 24 hours and it only becomes invalid once he finally resets the password. Or should I delete the token as soon as he clicks the link for some security concern? (all of this occurs before expiration)

2 Answers 2


You should not reset the token when the user clicks on it, because the user might be disturbed in the process (e.g. his cat jumped on the keyboard -- mine does that on an all-too-regular basis).

(Two days ago I was using such a link -- not for password reset, but similar -- which was deactivated as soon as I clicked on it, and it turned out that the page behind it was not compatible with Chrome. So I had to request a new link, doing the whole process one more time, and I cursed them for that. When dealing with passwords, you want and need to make a cooperative ally of the user, and certainly not to make him angry.)

When the password is actually reset, all pending password reset links should be deactivated. It is simpler if you allow only one reset link at a time; if the user requests a password reset while the previous link is still valid, just send it again (possibly, reset the timeout counter). There is no need for supporting several simultaneously valid, distinct password reset links. One link at a time means an easier database design, and thus less scope for bugs.

  • 1
    The problem is that you can't "just send it again" because the reset token in the above scenario has been hashed...
    – John
    Commented Feb 25, 2013 at 21:04
  • 2
    Then create a new one, and replace the hash in your database. If a new token is requested, there is little reason to keep the old one active, and there are good reasons (namely, to make things simpler) to keep only one link active at any time.
    – Tom Leek
    Commented Feb 25, 2013 at 21:22
  • 6
    But couldn't it be frustrating if they think the reset email didn't make it, they request another reset, and they think the new one came in but it's really the old one, they click the old one, and they're told it's invalid, wait for the new one? Is there any security concern about allowing multiple reset tokens as long as they all expire and as long as they're ALL deleted if the user completes the reset process?
    – John
    Commented Feb 25, 2013 at 21:26
  • 1
    I don't see a big issue in having several valid links floating around, except that it makes managing them harder. Not much harder, but still with more room for bugs.
    – Tom Leek
    Commented Feb 25, 2013 at 21:29
  • @John I think you can alleviate you issue of impatient users with a message "Please wait up to 10 minutes for your password reset to appears in your inbox. Please check your spam folder as well, and be sure to add [some email address] to your whitelist." I would think you either replace or keep the same for 24 hours depending on the risk tolerance.
    – Eric G
    Commented Feb 26, 2013 at 2:34
  • I would suggest allowing the user to request for a password reset only once so that you have only one reset token at a time.
  • You can always track if mail was sent successfully and only then store the reset token in the database.
  • If user tries to do it again (and an active reset link is present) notify the user saying that "reset link is already sent".
  • About deletion of the password tokens: They should be deleted instantly after the password has been successfully reset and not after clicking the rest link.
  • One possible alternative is to reset the password of the user and update it in the DB. Send a mail to the user notifying that "this is your new password change it immediately
  • Please note that password reset process will always be vulnerable if the e-mail communication is unencrypted. By time limiting the reset URL, one can try to minimize the attack window for a potential attack.
  • 1
    Hmm, I don't like the suggestion to send a temporary password to the user. This should not be done because most will be too lazy to change it. Even if you force them to choose a new password as soon as they log in, the temporary password will be active until they change it, unlike the reset token which expires.
    – John
    Commented Feb 26, 2013 at 18:31
  • @John the temporary password is supposed to be a random alphanumeric string like "we12lsi5" So the probability of a user keeping the same system generated password is highly unlikely.
    – Shurmajee
    Commented Feb 27, 2013 at 4:01
  • 1
    Yes, but until they log in and change it, the temporary password remains in an insecure channel. You can't expire the temporary password. Also, unless you force the user to choose a new password, many will be lazy and copy and paste the temporary one.
    – John
    Commented Feb 27, 2013 at 15:13
  • 2
    The expiration is what's important here, and it's critical because it at least minimizes the probability of a successful attack using the insecure email channel.
    – John
    Commented Feb 27, 2013 at 18:59
  • 1
    True, it doesn't PREVENT it, but it does make it harder. You're making the best of a bad situation.
    – John
    Commented Feb 28, 2013 at 19:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .