Recovery and operations
Design MFA and recovery
Add a second factor and recovery mechanism without making the fallback weaker than the primary authentication path.
Multi-factor authentication limits the damage of a stolen password. The attacker has the password but not the phone or the passkey, so they stay out. The cost is three new sensitive workflows: enrolling a factor, replacing it, and recovering when it’s lost. Each one is a new door into the account.
Independence is what makes a second factor work
A second factor helps only if compromising the first doesn’t hand over the second. A password plus a code emailed to the account whose password was just stolen is barely two factors. A password plus a passkey on a separate device is.
TOTP codes from an authenticator app are a solid middle ground. They stop password reuse from being enough. But a user can still be talked into typing a code into a phishing page, and the attacker relays it within the 30-second window. Passkeys close that gap because the credential is bound to your site’s origin. My preference: passkeys first, TOTP second, SMS and email codes last.
Enrollment is a privileged action
Turning MFA on, or adding a device, changes how the account can be entered. Protect it:
- Require recent authentication with an existing factor when one is enrolled.
- Prove possession of the new factor before activating it. For TOTP, don’t mark it active because the QR code was shown. Require one valid code first.
- Notify the user through an existing channel.
For TOTP, protect the stored seed like a credential, accept only a small clock window (one step either side), and reject a code already used inside that window. Removing or replacing a factor gets the same protection.
Recovery codes are credentials
Recovery codes are the “I lost my phone” path. Generate them with plenty of entropy, show them once, store only hashes, and consume each one atomically, as we did with reset tokens.
Don’t use security questions as a factor. Your mother’s maiden name is on Facebook, your first pet’s name is guessable, and you can’t rotate either one.
Support is part of the attack surface
The weakest factor is often a helpful support agent. Someone calls, sounds stressed, knows a few personal details, and gets MFA removed. Write down exactly what support may verify and what they may never override. For high-value accounts, add friction on purpose: a waiting period, multiple proofs, or a manual review.
Try this: draw the full lifecycle for the Books API. Enroll a factor, pass a challenge, add a second device, regenerate recovery codes, lose a device, remove a factor, recover the account. For every arrow, write what proof is required, what notification goes out, which sessions get revoked, and how an attacker would abuse it. The arrows without a good answer are your next tasks.
Lesson completed