6

I use SMS for MFA (yes I know it's bad, but better than no MFA) in an web application.

On login an OTP is sent to the user via SMS.

This OTP is valid until:

  • it expires after 10 minutes
  • it is submitted successfully (can only be used once)
  • it is entered incorrectly more than a 5 times (brute force protection)

So far, so normal. What I do differently than most implementations that I saw, is that if the user requests the OTP again, I send exactly the same OTP again. Most implementations send a new OTP and invalidate the original one.

I do this because of UX considerations, what if the user did for some reason not see the first SMS (or it is delayed because of some reason) and then mixes those two messages up.

My questions is: why do applications generally regenerate the OTP on resend? What are the possible attacks/security problems if I don't do this?

New contributor
Martin is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

3 Answers 3

16

It gives the user the ability to invalidate the OTP.

What if they know that someone saw, or knows that an unauthorised person gained access? A simple "send again" closes the exposure.

I'm not sure your UX concern is valid. It's pretty standard to send multiples. The timestamps (or the linear queue) in the messages keep them distinct.

5
  • 5
    That's a very good point. Although I think then I will have to make it clear that resending invalidates the current token. Maybe I am the only one, but I have this problem with multiple SMS frequently. Sometimes it just takes time for them to arrive and I resend them. And then I don't know which one is the current one. (Let's say I have 3 codes, I received 1 and 2, 3 was not yet received) Commented 2 days ago
  • 1
    @Martin Generate a random letter in front of the code, and return this to the UI for the first character suggestion. It can even be generated with a deterministic or pseudo random, because what follows is a code from your true random source Commented yesterday
  • I must admit, I've never worked in a phone system that was that badly broken as a standard way of operating, so, do take that into account for your users. Commented yesterday
  • 10
    I'm not sure your UX concern is valid As someone with a bad cell connection, I can tell you I love OP's idea. I have regularly asked for OTP, wait 5 min. I receive nothing, maybe something went wrong? Askefor OTP again, receive two messages at the same time, enter the wrong one, both are now invalidated. Commented yesterday
  • 3
    SMS is often linear in sequence these days, but it's not linear in principle. And the timestamp is applied on receipt so you can't use that either. I've had many issues, but even with the best network, if you have no signal when you request it, then try again, they'll arrive with the same timestamp when you do get a signal and in a random order (this is why we can't log in with SMS OTPs in our labs in work). Commented 12 hours ago
8

If you're storing and re-sending the same code for 10 minutes, then there's a UX issue that if the user requests it again after 9:59 then you'll be sending them a code that's immediately invalidated.

You could work around this by storing the code for 10 minutes, but only re-sending the same one for the first 9 minutes - but then you're in a position where sometimes you're resending the same code and sometimes you're not, and also having to store multiple valid OTP codes for each user with different expiration times. All of which adds complexity to the login process (an area you want to keep simple because it's easy to introduce security issues), for minimal gain.

4
  • That's an interesting observation. Haven't thought about this. But I think it's very unlikely that a user waits that long to enter the OTP. From an UX perspective I can live with this. I am wondering if there is still any security implication. Commented 2 days ago
  • 3
    @Martin I agree it's unlikely they'd wait that long - but as you say SMS is not always reliable (especially in some areas), and messages may get delayed or lost. My main security concern is that you're adding a whole load of extra code and complexity to the login process, which introduces more areas for mistakes. Commented 2 days ago
  • 2
    This sounds like the same issue OATH TOTP has (the regular 2FA apps), just with a longer timer, and I imagine it could use the same solution as well – where the OTP isn't randomly generated but derived from seed & (time/30), and it seems to me that it would be very little extra code to check input against the 'previous' and 'next' OTPs, which probably all TOTP implementations do already (e.g. if input == derive_totp(secret,time) becoming if input in {totp(s,t-interval), totp(s,t), totp(s,t+interval)}). Commented 2 days ago
  • That would have the advantage of making that part of the authentication stateless, though extends valid period by up to one period. Commented 19 hours ago
1

There are both benefits and downsides when you generate a new OTP on every request. A clear benefit is that it minimizes exposure of the OTPs: Each OTP is only sent exactly once over SMS (which you already said is an insecure channel), and each new OTP immediately invalidates the previous one, even before 10 minutes have elapsed. This is likely the reason why the approach is popular. On the other hand, generating new OTPs can indeed be confusing if the user has poor connectivity and receives SMS with a major delay.

Ultimately, you should try to replace SMS-transmitted OTPs whenever possible. Except for very, very old hardware, there's almost always a better option for 2FA:

  • Time-Based One-Time Passwords (TOTP) through an authenticator app or a dedicated hardware device (like a YubiKey); this completely avoids the problem of having to send the OTP from the application to the user
  • Web Authentication with passkeys
  • transmitting OTPs via Rich Communication Services (RCS)
  • a dedicated authentication app which receives the OTP through, e.g., Firebase Cloud Messaging

Like I said, SMS may indeed be the only option if you need to support legacy devices, but all other users should be able to choose a more secure alternative.

1
  • 1
    Although, from a UX point of view, RCS doesn't change anything, so this is still a problem there. Commented 14 hours ago

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.