What Is Two-Factor Authentication (2FA)?
Two-Factor Authentication (2FA) adds a second layer of verification beyond a password. Even if an attacker steals your password, they cannot log in without also possessing your second factor. The three categories of authentication factors are:
- Something you know — Password, PIN, security questions
- Something you have — Phone, hardware token, smart card
- Something you are — Fingerprint, face ID, voice
Most 2FA implementations combine a password (something you know) with a one-time code from a mobile app (something you have).
How TOTP Works
TOTP (Time-based One-Time Password) is defined in RFC 6238. It generates a 6-digit code that changes every 30 seconds, synchronized between your app and the server without any network communication.
Setup Process:
- The server generates a random secret key (usually 20 bytes / 160 bits).
- The server displays the secret as a QR code.
- The user scans it with an authenticator app (Google Authenticator, Authy, etc.).
- Both the server and app now share the same secret.
Code Generation:
counter = floor(currentUnixTime / 30)
HOTP = HMAC-SHA1(secret, counter)
TOTP = HOTP truncated to 6 digits
Because both parties compute the TOTP from the same counter (current time ÷ 30) and the same secret, they always arrive at the same 6-digit code — no network required.
Verification:
The server checks the submitted code against the current TOTP and usually the previous and next (to account for clock skew and network latency). A valid code is accepted once and invalidated to prevent replay attacks.
HOTP: The Counter-Based Predecessor
HOTP (HMAC-based One-Time Password, RFC 4226) uses an incrementing counter instead of time. The counter advances each time a code is generated.
- Advantage: Works without clock synchronization, good for hardware tokens.
- Disadvantage: Counter can get out of sync if codes are generated without being used.
TOTP is generally preferred for software authenticators.
Authenticator Apps
| App | Open Source | Multi-device | Backup |
|---|---|---|---|
| Google Authenticator | ❌ | iOS + Android | Cloud backup option |
| Authy | ❌ | Yes | Encrypted cloud backup |
| Microsoft Authenticator | ❌ | Yes | Cloud backup |
| Aegis | ✅ | Android | Encrypted file backup |
| Raivo | ✅ | iOS | iCloud backup |
For maximum security, Aegis (Android) and Raivo (iOS) are recommended — both are open source and support encrypted local/cloud backups.
TOTP Security Properties
Phishing Resistance
TOTP codes are valid for only 30 seconds. If a user is tricked into entering a code on a phishing site, the attacker must use it before it expires — and it can only be used once.
Replay Prevention
Because each code is time-limited and single-use, replaying an intercepted code won't work.
Brute Force Resistance
With 10^6 possible 6-digit codes and 30-second validity, an attacker can check 3 codes/second before the window expires. Lockout policies further limit attempts.
Limitations of TOTP
- SIM swapping — SMS-based 2FA is vulnerable; TOTP (app-based) is not.
- Real-time phishing — Sophisticated attacks proxy credentials in real time, bypassing TOTP. Hardware keys (FIDO2/WebAuthn) prevent this.
- Device loss — Losing your phone without backup codes locks you out. Always save backup codes.
- Account recovery — Many services have weak account recovery that bypasses 2FA entirely.
Implementing TOTP in Your Application
// Using 'otplib' (npm)
import { authenticator } from 'otplib';
// Generate secret (once, during user setup)
const secret = authenticator.generateSecret();
// Generate current TOTP
const token = authenticator.generate(secret);
// Verify user-submitted token
const isValid = authenticator.verify({ token, secret });
# Using 'pyotp' (pip)
import pyotp
secret = pyotp.random_base32()
totp = pyotp.TOTP(secret)
token = totp.now() # Current code
totp.verify(token) # Returns True
Using This Tool
This OTP generator accepts a TOTP secret key (Base32 encoded) and displays the current code along with a countdown timer. You can also validate a code against a secret — useful for testing your TOTP implementation.
→ Try the OTP Generator