Suppose I want to implement an OTP system that generates 6 to 10 digit numbers. (assume its used for reset password, or send money)

The OTPs have an expiry time, so they keep getting removed from the server's memory.

I have been looking around the Internet but could not find a single reference to the following best practice:

The "attacker/user" must supply the email along with the OTP to use it.

The reason I am asking is because I have a colleague who want to implement the OTP as follows:

  1. Generate OTP, store (OTP, email, expireTime, purpose) in server memory. If same OTP is generated again, the old entry is removed from memory.
  2. Send OTP to email.
  3. Ask ONLY OTP input from user (example /verifyEmail?OTP=100434).
  4. Get the (email, purpose) from server memory for the OTP
  5. Use the OTP for the purpose

I could not convince him that this is insecure as an attacker can simply generate random OTPs and call the routes, and automatically cause some actions. ("The OTP only expires in 3 mins", "only once in a while it will be an issue", "We used it in another project and it was fine", etc).

What I need is a blog post or article (not too technical) that explains WHY this is insecure.

Also, what are the ways to implement a good OTP system of 6 to 10 digits?

Is random OTP generation good enough?

My suggestion would be to require only (email, OTP) pair uniqueness rather than OTP uniqueness and require email + OTP to be supplied by user. Is this secure?

  • This becomes only a problem when an attacker has access to the account (or mail), i.e. can forge transactions that require an OTP or can read the mail and allow invalid transactions. In both cases, the email is known, so there is no real benefit. Additionally, enumeration of the space can easily be throttled to discourage it. Other scenarios lack a benefit for an attacker, making it not worthwhile. Yet, there are good solutions for real 2FA that should be used instead, in the spirit of "never roll your own"
    – Tobi Nary
    Sep 16, 2017 at 8:09

1 Answer 1


Your concern

When resetting a password it is a common practice to send a token to the user. The token being a long random string. You do not necessarily need the email address in the reset-URL.

You could call the reset URL with this token and reset the password for the account to which the token belongs.

But see this: If you are using a "6 digit token", these are only 1 mio possibilities. Then an attacker could try all values and this way he would be able to reset several passwords. And if the response is, "your password for [email protected] has been reset", then the attacker would get several accounts with freshly resetted passwords.

Without ANY NEED to intercept any email.

basically for transactions

You may also take a look at the defaults, TOTP (RFC6238) and maybe OCRA (RFC6287).

OCRA also lets you generate the OTP value based on transaction data - like the money to be sent.

You must log in to answer this question.

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