TOTPWhat is totp?Time-based One-Time Password - a 6-digit code generated from a shared secret and the current time, changing every 30 seconds. Powers authenticator apps. via authenticator apps is one of several 2FAWhat is 2fa?Two-factor authentication - requiring a second verification step (like a phone code) on top of your password to prove it's really you. methods, and it is not always the right choice. An internal admin tool for a three-person startup has different security requirements than a banking application with millions of users. Understanding the strengths and weaknesses of each method lets you make informed decisions, and lets you evaluate whether AI-generated authenticationWhat is authentication?Verifying who a user is, typically through credentials like a password or token. code chose the right approach.
SMS-based 2FAWhat is 2fa?Two-factor authentication - requiring a second verification step (like a phone code) on top of your password to prove it's really you.
SMS 2FA sends a one-time code via text message. The user enters the code on the login page. It is the most widely deployed 2FA method because every phone can receive text messages, no app installation required.
How it works
- User enters username and password
- Server generates a random 6-digit code and stores it with an expiration (typically 5-10 minutes)
- Server sends the code via an SMS providerWhat is provider?A wrapper component that makes data available to all components nested inside it without passing props manually. (Twilio, AWS SNS, Vonage)
- User receives the text and enters the code
- Server compares the entered code to the stored one
// SMS 2FA: server-side code generation and verification
async function sendSmsCode(userId, phoneNumber) {
const code = crypto.randomInt(100000, 999999).toString();
const expiresAt = Date.now() + 10 * 60 * 1000; // 10 minutes
await db.storeSmsCode(userId, hashCode(code), expiresAt);
await smsProvider.send(phoneNumber, `Your login code is: ${code}`);
}
async function verifySmsCode(userId, userCode) {
const stored = await db.getSmsCode(userId);
if (!stored || Date.now() > stored.expiresAt) return false;
if (!compareHash(userCode, stored.hashedCode)) return false;
await db.deleteSmsCode(userId); // Single use
return true;
}Why SMS 2FA is weak
| Attack | How it works | Difficulty |
|---|---|---|
| SIM swapping | Attacker convinces your carrier to transfer your number to their SIM card | Medium, requires social engineering the carrier |
| SS7 exploitation | Attacker exploits vulnerabilities in the phone network's signaling protocol to intercept texts | High, requires telecom access, but available for purchase |
| Phone number recycling | Your old phone number gets reassigned to someone else who now receives your 2FA codes | Low, happens naturally when you change numbers |
| Malware | Malware on the phone reads incoming SMS messages | Medium, depends on device security |
| Social engineering | Attacker calls support pretending to be the user, claims lost phone, requests code via alternative method | Medium, depends on support training |
In 2019, Twitter CEO Jack Dorsey's Twitter account was hijacked via SIM swapping. The attacker called the carrier, impersonated Dorsey, and had the phone number transferred. With SMS 2FA, this gave them full access.
NIST Special Publication 800-63B explicitly discourages SMS as a second factor due to these weaknesses. It is not banned, but it is classified as a "restricted" authenticator, meaning applications should offer at least one alternative.
Email-based 2FAWhat is 2fa?Two-factor authentication - requiring a second verification step (like a phone code) on top of your password to prove it's really you.
Email 2FA sends a one-time code or a magic link to the user's email address. It is common in consumer applications where users may not have an authenticator app installed.
Strengths and weaknesses
Email 2FA is only as secure as the user's email account. If the email is compromised (the most common account to be compromised), the attacker gets both the password reset link and the 2FA code. This makes email 2FA circular, you are securing account A with account B, and account B is often less secure.
| Factor | Email 2FA | SMS 2FA |
|---|---|---|
| Delivery reliability | High (unless filtered to spam) | High (unless carrier issues) |
| Delivery speed | Seconds to minutes | Seconds |
| SIM swap vulnerable | No | Yes |
| Phishable | Yes | Yes |
| Requires phone number | No | Yes |
| Works offline | No | Partially (SMS can be delayed) |
Email 2FA is acceptable as a fallback method or for low-risk applications, but it should not be the only option for high-value accounts.
Push-based 2FAWhat is 2fa?Two-factor authentication - requiring a second verification step (like a phone code) on top of your password to prove it's really you.
Push 2FA sends a notification to a dedicated app on the user's phone. The user taps "Approve" or "Deny." No code to type, no SMS to wait for. Duo, Okta Verify, and Microsoft Authenticator all support push notifications.
The MFA fatigue problem
Push-based 2FA has a specific vulnerability: MFA fatigue (also called push bombing or approval spamming). An attacker who has the user's password triggers login attempts repeatedly. Each attempt sends a push notification to the user's phone. At 2 AM, after 50 notifications, the user taps "Approve" just to make it stop.
This is exactly how the 2022 Uber breach happened. The attacker bought stolen credentials on the dark web, then bombarded an employee with push requests. After an hour of notifications, the employee approved one.
Mitigations for MFA fatigue
| Mitigation | How it works |
|---|---|
| Number matching | The login screen shows a random 2-digit number; the user must enter it in the push notification |
| Geographic context | The notification shows the login location ("Someone is trying to log in from Moscow") |
| Rate limiting | Limit push requests to 3 per 10 minutes per account |
| Lockout after denials | After 3 "Deny" taps, lock the account and alert security |
| Phishing-resistant alternatives | Offer hardware keys alongside push for high-risk accounts |
Number matching is the most effective countermeasure. Instead of a simple approve/deny choice, the user must look at their login screen, read the displayed number, and enter it on their phone. An attacker who is not sitting at the login screen cannot complete this step.
Hardware security keys (FIDO2What is fido2?A W3C standard for hardware-backed, phishing-resistant authentication using public-key cryptography - implemented by security keys and passkeys./WebAuthn)
Hardware keys, YubiKey, Google Titan, SoloKeys, are physical devices that plug into USB or communicate via NFC. They implement the FIDO2/WebAuthn standard, which is fundamentally different from TOTPWhat is totp?Time-based One-Time Password - a 6-digit code generated from a shared secret and the current time, changing every 30 seconds. Powers authenticator apps. or SMS.
Why hardware keys are the strongest option
TOTP and SMS are phishable. An attacker with a real-time proxy can capture the code as the user enters it and replay it to the real server. Hardware keys use public-key cryptography with originWhat is origin?The combination of protocol, domain, and port that defines a security boundary in the browser, like https://example.com:443. binding. The key signs a challenge that includes the website's domain, so a phishing site on a different domain cannot obtain a valid signature.
// WebAuthn registration (simplified, server-side)
const registrationOptions = {
challenge: crypto.randomBytes(32),
rp: { name: 'MyApp', id: 'myapp.com' }, // Origin binding
user: { id: visitorId, name: userEmail },
pubKeyCredParams: [
{ type: 'public-key', alg: -7 }, // ES256
{ type: 'public-key', alg: -257 }, // RS256
],
authenticatorSelection: {
authenticatorAttachment: 'cross-platform', // Hardware key
userVerification: 'preferred',
},
};The key difference: with TOTP, the secret is shared between the server and the user. If the server is breached, the attacker gets the secret. With WebAuthn, the server stores only the public key. Even a complete database breach does not give the attacker anything they can use to authenticate.
Passkeys: the evolution of WebAuthn
Passkeys extend WebAuthn by syncing credentials across devices via the platform's cloud (iCloud Keychain, Google Password Manager). They provide the phishing resistance of hardware keys with the convenience of not needing a physical device. Passkeys are rapidly being adopted by all major platforms.
The complete comparison
| Method | Phishing resistant | Offline capable | Cost | User friction | Best for |
|---|---|---|---|---|---|
| TOTP (authenticator app) | No | Yes | Free | Low | General-purpose 2FA for most apps |
| SMS | No | Partial | Per-message cost | Low | Fallback only, not primary 2FA |
| No | No | Minimal | Low | Low-risk apps, passwordless login | |
| Push notification | No (without number matching) | No | Provider cost | Very low | Enterprise apps with managed devices |
| Hardware key (FIDO2) | Yes | Yes | $25-$70 per key | Medium | High-security accounts, admin access |
| Passkey | Yes | Depends on device sync | Free | Low | Consumer apps, replacing passwords entirely |
Offering multiple methods
Production applications should support multiple 2FAWhat is 2fa?Two-factor authentication - requiring a second verification step (like a phone code) on top of your password to prove it's really you. methods. Users need options, someone without a smartphone cannot use TOTPWhat is totp?Time-based One-Time Password - a 6-digit code generated from a shared secret and the current time, changing every 30 seconds. Powers authenticator apps., someone traveling internationally may not receive SMS. The typical approach:
- Primary method: TOTP or hardware key (user's choice during enrollment)
- Backup method: recovery codes (always available, covered in the next lesson)
- Optional upgrade: hardware key for users who want maximum security
Store which methods each user has enrolled. During login, present only the methods the user has set up. Allow users to add, remove, or change methods from their security settings, but always require re-authenticationWhat is authentication?Verifying who a user is, typically through credentials like a password or token. before modifying 2FA settings.