Token codes may be stale
To reproduce
- Synchronize times on all systems.
- Import a new token into both Authenticator and another app (in my case, FreeOTP+ on Android).
- Compare token codes shown: are they the same? do they change at the same time?
- Log on to the target system with the code displayed by either app. For each app, make one try with a fresh code and with a code that is just about to expire.
Expected result
Both apps show the same code, and the code switches over at the same time. I can log on to the system with codes from either app, no matter if they are fresh or just about to expire.
Actual result
About half of the time, both apps show different codes. Authenticator switches codes somewhat later than FreeOTP+, to the code that FreeOTP+ has already been showing. Codes which, according to Authenticator, are just about to expire are sometimes rejected by the system, but I can log on with codes from FreeOTP+.
Looking a bit deeper into the delay, it appears that Authenticator always starts up with a reportedly fresh code (i.e. still valid for 30 seconds), whereas on FreeOTP+, even right after launching the app, remaining code validity may be anything from the maximum to “just about to expire”.
Software version
Authenticator 3.32.2, bundled with Ubuntu MATE 22.04
Additional information
As I understand TOTP (as per the Wikipedia article), the switchover should occur when Unix time is an exact multiple of the code validity period. In my case, codes are set to be valid for 30 seconds, thus the switchover should occur at precisely 0 and 30 seconds past each full minute.
This is the case with FreeOTP+, which is less than a second off. Authenticator, on the other hand, seems to have an offset which varies with each time I started the app. In one case it was roughly 27 seconds behind, making it near-impossible to log on with codes set to expire after 30 seconds.
Longer grace periods on the server (and to an extent longer validity periods for the code) will alleviate this issue to an extent, albeit at the cost of security.
As mentioned above, Authenticator seems to count token expiration from the time the app is started, rather than from the beginning of the epoch. If launched n seconds into the validity period of a code, it will display a stale code for the last n seconds before the switchover (which are the first n seconds of the new token’s validity period).
Thus, as I understand it, the fix would be to determine when the next code change is due on app startup, rather than counting down from 100%.