MFA stands for multi-factor authentication. It adds another proof step after or alongside the primary login factor.
For backend developers, MFA is not only a UI feature. It affects sessions, recovery, risk decisions, user support, account security, and sensitive actions.
Quick answer
MFA requires more than one type of authentication factor.
Common factors include:
- Something the user knows, such as a password.
- Something the user has, such as an authenticator app, hardware key, or trusted device.
- Something the user is, such as a biometric unlock handled by a device.
For many web apps, the practical starting point is password login plus TOTP authenticator apps or WebAuthn/passkeys. SMS can be better than no second factor, but it has security and reliability tradeoffs.
Why MFA matters
Passwords get reused, phished, leaked, guessed, or captured by malware.
MFA reduces the chance that a stolen password alone is enough to take over an account. It is especially important for admin users, billing actions, password changes, production consoles, data exports, and account recovery.
MFA does not make an app invulnerable. Attackers may still target session cookies, phishing flows, recovery channels, OAuth grants, or support processes.
Read Password Hashing Explained for what password storage protects and what it does not protect.
Common MFA methods
| Method | How it works | Tradeoff |
|---|---|---|
| TOTP app | User enters a rotating code from an authenticator app | Widely supported, but codes can be phished |
| WebAuthn/passkey | Browser and device perform a cryptographic challenge | Strong phishing resistance, but UX and device support need planning |
| Backup codes | User stores one-time recovery codes | Useful for lockout recovery, risky if stored poorly |
| SMS code | Code sent by text message | Easy to understand, but weaker and dependent on phone network |
| Email code | Code sent by email | Convenient, but only as strong as email account security |
The right method depends on user base, account value, compliance needs, and support capacity.
MFA enrollment flow
Enrollment is where a user turns MFA on.
A backend-friendly flow usually includes:
- Confirm the user recently authenticated.
- Generate or register the second factor.
- Ask the user to prove the factor works.
- Store factor metadata securely.
- Generate backup codes.
- Record an audit event.
- Notify the user that MFA was enabled.
Do not mark MFA as enabled before the user successfully verifies the factor. Otherwise a failed setup can lock the user out.
For sensitive accounts, require MFA setup before granting high-risk roles. Read RBAC vs ABAC for access control model tradeoffs.
MFA during login
After password verification, the backend may create a partially authenticated state.
That state says: the password was correct, but MFA is still required.
Avoid treating the user as fully logged in before MFA succeeds. The app should not expose account data, API tokens, billing pages, or user settings during this intermediate state.
Example state machine:
anonymous -> password_verified_pending_mfa -> authenticated
The intermediate state should be short-lived, scoped, and protected from confused authorization checks.
Read JWT vs Session Authentication for session and token architecture tradeoffs.
Step-up authentication
Not every app needs MFA on every login.
Some systems use step-up authentication. The user may be logged in normally, but the app requires another factor for sensitive actions.
Examples:
- Changing password or email.
- Viewing recovery codes.
- Adding a payment method.
- Creating an API key.
- Exporting sensitive data.
- Assigning admin roles.
Step-up checks are authorization-related. The backend should verify that the session recently completed the required factor before allowing the action.
Recovery and backup codes
Recovery is often the weakest part of MFA.
If users lose their phone or hardware key, they need a safe way back in. But if recovery is too easy, attackers can bypass MFA by targeting support or email.
Useful recovery practices:
- Provide one-time backup codes.
- Show backup codes only at creation time.
- Store only hashed backup codes where possible.
- Notify users when recovery codes are used or regenerated.
- Require stronger proof for support-assisted recovery.
- Revoke suspicious sessions after recovery.
MFA implementation is partly a security feature and partly a support workflow. Plan both.
Common mistakes
The first mistake is treating MFA as complete after the frontend displays a QR code. The backend must verify the factor before enabling it.
The second mistake is creating a normal session before MFA is complete.
The third mistake is not protecting MFA reset and recovery flows.
The fourth mistake is storing backup codes in plaintext.
The fifth mistake is using one broad “MFA enabled” flag without tracking method, enrollment time, recovery state, and recent step-up verification.
The sixth mistake is not logging MFA changes. Security teams and users need visibility into factor enrollment, removal, and recovery.
Practical recommendation
For many web apps, start with MFA for high-risk users and actions:
- Admin accounts.
- Billing managers.
- Production operators.
- Users who can export data.
- Users creating API keys or OAuth apps.
Use TOTP as a reasonable baseline if WebAuthn/passkeys are not ready. Add backup codes and careful recovery from the beginning.
Keep the backend model explicit: pending MFA, completed MFA, recently verified MFA, available recovery methods, and audit events are different states.
Related reading
Read Password Hashing Explained for the password layer and Authorization vs Authentication for the boundary between proving identity and granting access.
Read Session Fixation Explained, JWT vs Session Authentication, and SameSite Cookies Explained when designing the authenticated session after MFA. For the full sequence, browse the Backend Security Learning Path and the Topics map.