Introduction
TOTP (Time-based One-Time Password) generates 6-digit codes that change every 30 seconds based on the current time. If the user's device clock drifts from the server clock -- due to device time settings, battery removal, or timezone changes -- the generated codes will not match the server's expected value, causing MFA authentication to fail.
Symptoms
- User enters correct TOTP code but authentication is rejected
- MFA works after resyncing the authenticator app but fails again later
- Users report MFA failures after traveling across timezones
- Server logs show
TOTP code mismatchfor valid-looking codes - Error message:
Invalid MFA code. Please check your device time and try again.
Common Causes
- User device clock not synchronized with NTP (manual time setting)
- Device battery removed, causing the real-time clock to reset
- Timezone change on the device without automatic time update
- Server TOTP window tolerance too narrow (only checking current time step)
- Authenticator app cache stale after device timezone change
Step-by-Step Fix
- 1.Verify the user device time is synchronized: Check the device clock.
- 2.
` - 3.# On the user's device:
- 4.# iOS: Settings > General > Date & Time > Set Automatically = ON
- 5.# Android: Settings > System > Date & Time > Automatic date & time = ON
- 6.# Compare device time with: https://time.is/
- 7.
` - 8.Resync the authenticator app: Force a time correction in the app.
- 9.
` - 10.# Google Authenticator:
- 11.# Settings > Time correction for codes > Sync now
# Microsoft Authenticator: # Settings > Automatic time correction > Enable
# Authy: # Settings > Time correction > Sync now ```
- 1.Increase server TOTP window tolerance: Allow for clock drift.
- 2.```python
- 3.# Python pyotp example with window tolerance
- 4.import pyotp
- 5.totp = pyotp.TOTP(secret)
- 6.# Check current and adjacent time steps (window of 1 = +/- 30 seconds)
- 7.# Window of 2 = +/- 60 seconds
- 8.is_valid = totp.verify(user_code, valid_window=2)
- 9.
` - 10.Re-provision the TOTP secret if resync does not help: Generate a new QR code.
- 11.
` - 12.# In the application:
- 13.# 1. Disable MFA for the user
- 14.# 2. Re-enable MFA and display a new QR code
- 15.# 3. User scans the new QR code with their authenticator app
- 16.# 4. Verify the new code works
- 17.
` - 18.Implement backup authentication methods: Provide fallback options.
- 19.
` - 20.# Offer alternative MFA methods:
- 21.# - SMS-based OTP (less secure but available)
- 22.# - Email-based OTP
- 23.# - Recovery codes (one-time use)
- 24.# - Hardware security keys (FIDO2/WebAuthn)
- 25.
`
Prevention
- Configure server TOTP tolerance window of at least 2 (plus/minus 60 seconds)
- Provide clear instructions for users to enable automatic time sync on their devices
- Offer multiple MFA methods so users have fallback options
- Monitor MFA failure rates and alert on sudden increases that may indicate time drift
- Implement adaptive MFA that allows recovery codes when TOTP repeatedly fails
- Educate users about the importance of device time synchronization for MFA