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):
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!"
- 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.
- 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.
- On Linux, use
sudo timedatectl set-ntp true.
- Regularly monitor the server’s clock drift.
- 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!