0

I'm building an OTP and have implemented the ROTP gem. However, the behaviour of the ROTP is not what I expected it to be.

For instance, when requesting a ROTP with 30secs of interval

at 15:00:14, this will return you an OTP say 212321
at 15:00:30, however, this will return you a new OTP say 312932

Notice how it hasn't reached 30 secs of expiry but already returns you a new otp

My expected behaviour of a time based OTP is

at 15:00:14, this will return you an OTP say 212321
at 15:00:30, will still return 212321
at 15:00:44, will return a new OTP because it has reached the 30 secs of expiry interval

How can I achieve my expected behaviour of a time based OTP?

Steve Vinoski
  • 19,847
  • 3
  • 31
  • 46
Realizt30
  • 173
  • 2
  • 12
  • The expiration is based on the wall clock, not on when the code was generated. Have you ever used a TOTP system for your own accounts? You will notice in any time-based system that when you "generate" a new code, it is typically already on its way to expiration. Often, if you're too close to expiration, you'll have to wait for a new code to come around. – user229044 Jul 22 '21 at 13:08

1 Answers1

1

A generated one-time-pad does not have a built-in expiration in the token. That is: the TOTP algorithm ensures that during a certain fixed timeframe, the same token is generated.

In your case, the 212321 token is valid from 15:00:00 until 15:00:29, regardless when during this timeframe you have generated it. At 15:00:30, a new time slot starts and your generated token will be 312932 and stay at that value until 15:00:59. This is inherent to the TOTP algorithm defined in RFC 6238.

This behavior is important because the server checking the validity of the token will use the very same algorithm to generate the token for the current time slot and compare it to the token given by the client. Depending on when exactly the client provides the token, you have a bit more or a bit less wiggle-room.

In order to allow for some clock-drift and to provide a slightly better usability, the rotp gem verifier component has an option for a drift_behind value to still allow technically expired tokens for some time. See https://github.com/mdp/rotp#verifying-a-time-based-otp-with-drift for details.

Holger Just
  • 52,918
  • 14
  • 115
  • 123
  • Thanks for the explaination. I'm not aware of such algortihm defined in the RFC. Anyways, the problem that I'm trying to solve is basically to check whether the User requests within the expiry time (currently it's by checking whether it's the same OTP). But I think I need to adjust it so that it checks by whether (request time minus otp last sent at) is still within the drift interval. – Realizt30 Jul 22 '21 at 15:41