I've implemented a password reset function for a website I'm working on. By default, the function is very fast, and I'm wondering if it would be helpful, from a security standpoint, to intentionally slow it down a little.

I'm thinking of simply adding a sleep call at the start of the controller action.

My reasoning is, a user who is genuinely trying to reset their password, probably won't be bothered by waiting an extra 5 seconds or so, to receive the confirmation that the password reset email has been sent. However this extra 5 seconds, I'm hoping could help slow down a bot.

One of my main reasons for wanting to do this, is because previously the reset function didn't give any indication if an invalid username was entered. This was to prevent malicious users from attempting to find valid usernames. I've been asked to change this though as users were finding it confusing.

As the reset function can now be used to determine if a username is valid, I wanted an extra level of security to help prevent malicious use.

  • Doesn’t the reset link go always to the legitimate user’s email ?
    – elsadek
    Sep 1, 2018 at 22:52
  • Yes, the reset link goes to the legitimate users email. Sep 1, 2018 at 22:53
  • My main concern is that the function can be used to determine valid usernames. Even though it may still be difficult for hackers to use that information. Sep 1, 2018 at 22:54
  • 1
    Anyone trying to discover if a username already exists just have to try to register said username.
    – ThoriumBR
    Sep 1, 2018 at 22:58
  • 2
    Implemented badly, this could provide a mechanism for DOSing your website; proceed with care.
    – symcbean
    Sep 2, 2018 at 1:00

5 Answers 5


There's no need to make it possible to enumerate usernames via the password reset function. Simply offer a box for an email address (or username, if email addresses aren't guaranteed to be unique in your system), and any time somebody enters one, give them a message saying "if we have (that address|an address corresponding to that user) in our system, we have sent an email. Please check your email, and note that it may take a few minutes for the message to arrive. The email will be valid for [some short time]."

If you want to slow down attempts to abuse the password reset system anyhow, a good CAPTCHA is probably a better bet than an artificial delay.

Also, I echo everything in @neonprimetimesecurity's second paragraph, with the addition that not only should the link be cryptographically random and unguessably long, it should no longer work after one use regardless of the time remaining until it expires. (You can make "one use" mean "once the password is actually reset" if you want, sometimes people run into issues with email scanning services that request every URL in an email and end up invalidating links before the user gets them.)


There is always benefit from a security perspective if you can slow down an attackers/bots (captcha , sleep statements , etc) without impacting normal business use cases , but I think that's more of a call on your part , weigh the ROI and determine if it's worth it.

I think if you're threat modeling a bigger initial concern than enumerating usernames would be to ensure your password reset process itself is secure so that nobody can take over an account with it. Is the email validated? Are you sending a password reset link instead of a password ? Is that link temporary and expires ? Is that link random and not guessable ?


You are right that an "unguarded" password reset function could be used maliciously, e.g. for user enumeration or spamming your users with emails.

However, a call to the sleep function could make you vulnerable to DOS attacks! Your server probably has some explicit or implicit limit on the number of concurrent HTTP requests it can handle. If you got an endpoint that will take at least five seconds to complete, that's bingo for an attacker!

Calling sleep doesn't really limit how many requests the attacker can make - she doesn't even need to wait around for the response. It just makes you waste more system resources.

What you want to implement is some kind of rate limiting, e.g. based on IP address, or a CAPTCHA.

  • How is calling sleep a DoS concern? With or without the sleep, it takes the same total number of requests to reach the same amount of CPU time and the same amount of RAM consumption. It takes fewer requests per second to reach a certain amount of RAM, but is this really a concern? An attacker who wants to DoS can probably make far more complex requests such as a password verification (which takes a lot of CPU time and RAM unless you're doing it wrong). Aug 8, 2019 at 7:05
  • @Gilles If there is a limit on the number of concurrent requests the server can handle (e.g. if there is an Apache involved somewhere) you can fill up that pretty easily if there is a request that takes time, even though it doesn't use system resources.
    – Anders
    Aug 8, 2019 at 7:42

As Anders says, pausing your code means that it is occupying resources on your server for longer - so you are creating a possible avenue for denial of service. You could implement the delay at the client - but this is something the user can control and therefore ineffective in its objective.

Not limiting the rate control provides an avenue for DOS against the target mailbox.

A potential solution is to disallow reset rests for a window after a reset code has been issued.

You do not control the speed at which the email appears in the user's mailbox. So not restricting the rate at which resets are requested could undermine the legitimate use of the facility - user requests password reset. Email with reset code 'A' is sent to mailbox. User gets bored waiting and issues subsequent reset. Email with reset code 'B' is sent to mailbox. Email 'A' arrives at mailbox and is activated by the user. This is rejected by the site which is now waiting for reset code 'B'. Conversely, an attacker can keep hitting a site with invalid reset codes thereby preventing the legitimate user from resetting their password.

Such a simple thing quickly gets very complicated.

This is the fun of programming!

  • Thanks. This is very helpful. At the moment the reset codes are single use and have a relatively short expiry time, but currently there isn't any restriction on the number of reset codes that can exist simultanously for an individiual user. I probably should have it lock the account if a lot of resets are requested in a short period of time. It might result in a support call, but that's better than a potentially compromised account. Jul 10, 2019 at 2:24

You could delay the function, but as an outside process, not inside it.

I explain:

User forgot the password, so he asked for a reset. Send him a link that will work only after 5 or 10 minutes. If the link is used before that, ask the user to wait until those minutes have passed.

Send a message to the primary and backup emails for the user stating someone from certain IP, browser and OS is trying to reset his password, with a link to cancel the request if isn't him.

After the wait, the user can access the page to change the password. You could lock the user out for a couple more minutes, sending a mail to the user telling him his password was changed and with a link to revert the change if he wants to. So save both the old and the new passwords on the database before the change occurs.

Using this, you will not DoS yourself, or lock out the user, and create a delay giving the user a slight chance to revert a change he haven't started. And make a couple users furious, of course...

  • That's an interesting approach. We currently don't have backup email addresses though, so wouldn't work in this situation. Also I think making users wait a while to reset passwords is likely to cause some issues. Aug 9, 2019 at 0:07
  • Making a user wait indeed creates issues, but an user losing access to his account creates way more issues. I believe the trade-off is worth the hassle.
    – ThoriumBR
    Aug 9, 2019 at 1:50

You must log in to answer this question.

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