TL;DR
Users sometimes enter incorrect Time-based One-Time Passwords (TOTPs). This guide explains how to handle these errors securely and improve the user experience. Focus on rate limiting, clear error messages, account recovery options, and logging for security monitoring.
Handling Incorrect TOTP Tokens
- Rate Limiting: Prevent brute-force attacks by limiting the number of incorrect TOTP attempts allowed within a specific timeframe.
- Implement this on your server-side code, not just in the frontend.
- Example (using Python and Flask):
- Consider increasing the lockout duration with each subsequent attempt.
- Clear Error Messages: Provide informative but not overly revealing error messages to users.
- Instead of saying “Incorrect TOTP code”, use “Invalid verification code. Please check your authenticator app and try again.”
- Avoid indicating whether the code is too old or too new.
- Account Recovery Options: Offer alternative recovery methods if a user loses access to their TOTP device.
- Backup Codes: Generate and securely store one-time use backup codes during initial setup. These should be presented to the user only when they cannot access their authenticator app.
- Email/SMS Recovery: Allow recovery via a registered email address or phone number, but with strong verification steps (e.g., security questions, confirmation links). Be aware of SMS interception risks.
- Account Reset: As a last resort, provide an account reset option that requires verifying the user’s identity through other means.
- Time Synchronization: Ensure your server’s time is accurately synchronized using NTP (Network Time Protocol). TOTP algorithms are highly sensitive to timing discrepancies.
- On Linux, use
sudo timedatectl set-ntp true.
- Regularly monitor the server’s clock drift.
- Logging and Monitoring: Log failed TOTP attempts for security monitoring purposes.
- Record timestamps, user IDs (if applicable), IP addresses, and any other relevant information.
- Set up alerts to notify you of suspicious activity, such as a high volume of failed attempts from a single IP address.
- Do *not* log the TOTP codes themselves!
- Authenticator App Compatibility: Test your implementation with various popular authenticator apps (Google Authenticator, Authy, Microsoft Authenticator) to ensure compatibility and correct time drift handling.
- User Education: Provide clear instructions on how to set up and use TOTP authentication, including information about backup codes and account recovery options.
from flask import Flask, session, request
import time
app = Flask(__name__)
app.secret_key = 'your_secret_key'
@app.route('/login', methods=['POST'])
def login():
if 'failed_attempts' not in session:
session['failed_attempts'] = 0
session['failed_attempts'] += 1
if session['failed_attempts'] >= 5: # Allow 5 attempts
return "Too many failed attempts. Try again later.", 429
# ... your TOTP verification logic here...
return "Login successful!"

