Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support resync in TOTP validation #11

Open
jjude opened this issue Dec 12, 2014 · 10 comments
Open

Support resync in TOTP validation #11

jjude opened this issue Dec 12, 2014 · 10 comments

Comments

@jjude
Copy link

jjude commented Dec 12, 2014

Consider this test:

import pyotp
from time import sleep

key = pyotp.random_base32()
for i in range(1,10):
  otp = pyotp.TOTP(key).now()
  sleep(5)
  print pyotp.TOTP(key).verify(otp)

Sample output is:

True
False
True
True
True
True
True
False
True

I have seen this in production. I don't know why it fails sometimes. Any idea why? And how I can go about fixing it?
Thank you,
Joseph

@thanatos
Copy link

Looking at the implementation, I think I can answer this. The Wikipedia article on TOTP notes, emphasis mine,

Both the server and the client compute the token, then the server checks if the token supplied by the client matches the locally generated token. Some servers allow codes that should have been generated before or after the current time in order to account for slight clock skews, network latencies and user delays.

pyotp, simply, does not (see here). It would be great if this could be an option, I think.

@AndCycle
Copy link

the only totp python package that have time skew support is SpookyOTP,
this should be easy to make it support, if anyone do the task.

@kislyuk
Copy link
Member

kislyuk commented Aug 22, 2015

I am repurposing this issue for skew support, and changing the title accordingly. If anyone has a preferred API for how this would work, please comment here.

@kislyuk kislyuk changed the title Sometimes fails Support clock skew and resync in TOTP validation Aug 22, 2015
@kislyuk
Copy link
Member

kislyuk commented Aug 22, 2015

From https://tools.ietf.org/html/rfc6238#section-6:

   Because of possible clock drifts between a client and a validation
   server, we RECOMMEND that the validator be set with a specific limit
   to the number of time steps a prover can be "out of synch" before
   being rejected.

   This limit can be set both forward and backward from the calculated
   time step on receipt of the OTP value.  If the time step is
   30 seconds as recommended, and the validator is set to only accept
   two time steps backward, then the maximum elapsed time drift would be
   around 89 seconds, i.e., 29 seconds in the calculated time step and
   60 seconds for two backward time steps.

   This would mean the validator could perform a validation against the
   current time and then two further validations for each backward step
   (for a total of 3 validations).  Upon successful validation, the
   validation server can record the detected clock drift for the token
   in terms of the number of time steps.  When a new OTP is received
   after this step, the validator can validate the OTP with the current
   timestamp adjusted with the recorded number of time-step clock drifts
   for the token.

   Also, it is important to note that the longer a prover has not sent
   an OTP to a validation system, the longer (potentially) the
   accumulated clock drift between the prover and the verifier.  In such
   cases, the automatic resynchronization described above may not work
   if the drift exceeds the allowed threshold.  Additional
   authentication measures should be used to safely authenticate the
   prover and explicitly resynchronize the clock drift between the
   prover and the validator.

It seems unambiguous that a "max_skew" parameter is needed, in number of time steps. The questions I have are:

  • Is there any need to parameterize the forward and backward max skew separately?
  • How exactly should resync work? i.e. if I record that the prover sent a proof from 3 timesteps ago, do I immediately adjust the expected skew to -3 and recenter the window of acceptance around it, or what?
  • How to incorporate resync into the pyotp API, if at all?

@tilkinsc
Copy link

Was this resolved in a commit?

@kislyuk
Copy link
Member

kislyuk commented Mar 16, 2017

There is a new parameter, verify(valid_window=...), which allows for a fixed amount of skew, just like max_skew above. There is no resync capability yet.

@tilkinsc
Copy link

Why would there need to be resync capabilities? Your computer isn't going to jump a second ahead or a second behind. The reason why it initially failed was because such a reason and TOTP implementation requests that there is a TTL component. Is this really necessary for the library to have (especially since you have to take latency into account and have the user give you the ms delay and fix and yada yada)

@kislyuk
Copy link
Member

kislyuk commented Jun 13, 2017

Please read the RFC, it explains the use case for clock skew support and resynchronization.

@legkoszkur
Copy link

Still have similar issue in 2023, always my first probe fails even my keys are the same and interval is setup on 30.

@kislyuk kislyuk changed the title Support clock skew and resync in TOTP validation Support resync in TOTP validation Oct 14, 2023
@kislyuk
Copy link
Member

kislyuk commented Oct 14, 2023

Clock skew is supported via the valid_window keyword argument.

Because resync is stateful, I don't think this library will fully support resync functionality directly. I think what we need in PyOTP to support resync is the ability to return where in the valid window the code was accepted, and documentation on how to use that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants