I'm designing a password reset system for my website/app right now and I'm not sure if the solution that I've reached could be considered suitably secure. The steps for resetting a password are as follows:

  1. User visits the login page (HTTPS) and chooses 'Forgot Password'.
  2. The user submits their email address (or username as the app allows sign-in with either).
  3. If no account is found with the provided email/username then no email is sent (user is not warned of this to prevent user enumeration).
  4. A 6 digit number is randomly generated as the reset token and stored in a key-value store (with the key being the token and the value being the user's ID). This store entry is configured to expire after 1 hour.
  5. The token is sent to the account's email address.
  6. The user then submits the token onto the same page that they provided their email on (the page contents changes to provide an input for the token).
  7. If the token is valid then the corresponding store entry is prematurely expired and the user is prompted to provide the new password (with a 'repeat password' input to double-check).
  8. On submission of their new password, the user's database record is updated to reflect this change and all active login sessions are invalidated.

This system doesn't use the standard method which involves generating a longer token (which comprises of a larger character set than just numerical digits); is this considered insecure?

My reasoning for this method is that our app is being developed for young people (specifically children and teens) and so this password reset system should be as simple as possible. This system means that the user doesn't have to change the page they're on (as the form to provide the reset token is automatically displayed after the email is sent) and they don't have to open any link from the email meaning that only one browser tab is ever used (and it's the same tab).

And from what I can tell, another benefit to this system is that password reset token is never exposed to any logs as it's never included in any URLs, although it's still exposed in the email however that's not something I can get around.

Can this system be considered suitably secure?

Also, would implementing a CAPTCHA service anywhere make this system more secure, or should I only ever consider adding one if we start to see too many requests being made?

1 Answer 1


The password reset scheme you describe looks OK, but you are leaving several questions unanswered at point 7, which are relevant for evaluation:

  • What happens, if the token the user submitted is wrong?
  • How many tries do you give the user before considering the reset attempt failed and block further token submissions?
  • If a reset attempt failed, can a user retry resetting his password again?
  • Is there any rate limiting (e.g. only one password reset attempt per account per day)?
  • Do you monitor failed attempts and react to such attacks (e.g. block an offenders IP address)?

The answers to these questions allow you to calculate the probability of an successful brute-force attack.

6 digits means a number in the range from 000000 to 999999. This gives you one million different possible tokens. Let's assume you allow up to 10 token submissions per reset attempt before you consider it failed and block further attempts. This gives an attacker a slightly better chance of success than 0.001% for a reset attempt.

That seems like a low probability, but if the attacker can automate the process and there are no limits how often a password reset can be triggered, a successful attack becomes likely fast. If an attacker makes 10000 such attempts, he has a probability of success to reset at least one account of around 10%. Ramp this up to 100000 attempts and you we are talking of a success rate of around 64% to reset at least one account. This does not look secure at all anymore.

So the real question is, can you prevent an attacker from making such a huge amount of reset requests, considering that it doesn't matter if they are done for a single account or multiple accounts.

You also talked about simplicity of the process. If you do not want to use a complex character set for the token, that's totally fine. Length is much more important anyway. If you want to make the token stronger, I would recommend adding a few extra digits. But in the ends, it comes down to protect against brute-force attempts.

  • I think that the process could be still suitably simple if I extended to a larger character set (I was only using 6 numerical digits as a baseline taken from TOTP code formats), such as numbers and lowercase characters. I could also slightly extend the length to 8 (displaying it as 2 blocks of 4). This would give me 2.8e+12 possible tokens, and I think would still retain the simplicity.
    – Luke Carr
    Apr 10, 2020 at 13:49
  • RE: your questions, I was considering allowing for 3 attempts at providing a token before that request becomes invalid and limiting each account to 3 requests per day. This would limit an attacker to 9 attempts at an account per day, from which I calculate the rate of success to be (3*3) / (36^8) = 3.19e-12. Correct me if I'm wrong.
    – Luke Carr
    Apr 10, 2020 at 13:53
  • @LukeCarr - yes, this sounds reasonable. Even if an attacker knows the email address of several 1000 users on your site, the chance of success is still small. I would consider this a scheme strong enough for most use cases and risk profiles.
    – Demento
    Apr 10, 2020 at 14:03
  • Thanks for your help. Is there any benefit to using a CAPTCHA at any stage of this flow or does it not really provide any benefit.
    – Luke Carr
    Apr 10, 2020 at 14:10
  • If you have a userbase of 100,000 users, and if the attacker can hit the "forgot password" for all of them, then even using just 123456 on all of them, there's a 10% chance (1 million possible tokens, 100,000 attempts) of hitting something. You should probably think of limiting not just the token attempts per user, but number of "forgot password" hits per hour across users.
    – user88917
    Apr 19, 2020 at 2:01

You must log in to answer this question.

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