0

In my python project i am planning to use TOTP.

A new User enter his email. Then he recieves a OTP generated using TOTP.

import pyotp
totp = pyotp.TOTP('base32secret3232')
totp.now() # => '492039'

The OTP is valid for 30s.

Now one can enter a fake email and use this same OTP which will be valid till 30s.

totp.verify('492039') # => True

So how to protect from such things.

Till the user's email is verified i dont want to save the firt time user in database

Santhosh
  • 9,965
  • 20
  • 103
  • 243
  • so you don't want save the email until it is verified or you don't want to generate otp for a fake email id – Shubham Shaswat Feb 04 '20 at 09:17
  • Your OTP implementation abould prevent that. – Klaus D. Feb 04 '20 at 09:18
  • @KlausD. can you explain how. I am not storing any information when a first time user is trying to use it. Once the first time user is verfied then i can have a separate secret key for each user and avoid any misuse – Santhosh Feb 04 '20 at 09:19

1 Answers1

2

From the PyOTP docs:

At minimum, application implementers should follow this checklist:

...

  • Deny replay attacks by rejecting one-time passwords that have been used by the client (this requires storing the most recently authenticated timestamp, OTP, or hash of the OTP in your database, and rejecting the OTP when a match is seen)

...

So when using a TOTP, you have to store something. There's no way around that.

Also note that 30s is a pretty short time for email-based OTPs. If the mail server is only a bit slow, the OTP will have expired.


There is an alternative approach for verifying email addresses that doesn't require you to store anything. In the email, include a link with a query parameter that is encrypted using a key that only your server knows. In the encrypted data, include the email address and registration timestamp. The server decrypts this, checks that the timestamp is still within acceptable range, and adds the email address the database.

Theoretically, there's not even a reason to encrypt; signing would serve the purpose. But the client has no need to know the URL contents, so we might as well not reveal it.

Thomas
  • 174,939
  • 50
  • 355
  • 478
  • Thank you for the clarification that i have to store something. Thanks for the alternate method also. For me i have to login the user using the OTP. So it acts like a dual purpose. – Santhosh Feb 04 '20 at 09:59
  • Also how about creating a new key `(i.e TOTP(key))` for each user request and send it in response by keyhasing using HMAC and then get it back with the OTP and then check it. Will the HMAC compromise the security of the TOTP key are can we be assured its very safe – Santhosh Feb 04 '20 at 10:04
  • I'm not sure I understand the question, but you may want to take a look at [nonces](https://en.wikipedia.org/wiki/Cryptographic_nonce). – Thomas Feb 04 '20 at 10:06
  • I feel storing the OTP will not help. Assuming the validity period is 3 minutes. The issue is the OTP generated will be same within that 3 minutes time frame. Even i store the OTP generated for an email eg: `test@test.com` it will not help me. Because another email `test2@test.com` requests for an OTP within 3 minutes, he will also recieve the same OTP. Then he can misuse the process – Santhosh Feb 04 '20 at 10:36
  • Please read up on how OTP works before you try to implement it. Of course you will never be generating the same OTP for multiple users (apart from one-in-a-million coincidence). – Thomas Feb 09 '20 at 08:48