Adding two-factor authentication to a login flow feels like a meaningful, comprehensive security upgrade, and the confidence that comes with it is understandable, it genuinely is real, valuable protection. Worth being precise about exactly what it protects, though, because it's a much narrower fix than the confidence around it usually suggests.
What 2FA actually solves
Two-factor authentication protects against one specific scenario extremely well: someone else obtaining a user's password, whether through a data breach elsewhere, a phishing attempt, or simple guessing, and using it to log in. Requiring a second factor, a code from an app, a text message, a hardware key, means a stolen or guessed password alone isn't enough to get in. That's a real, well-documented, valuable protection, and it's worth having.
What it has absolutely no relationship to
Every single access-control issue I've written about this year exists entirely on the other side of a successful login. Whether one logged-in user can see another user's data. Whether an admin route actually checks who's asking. Whether an API correctly scopes a query to the requesting user. Two-factor authentication has zero involvement in any of these questions, because by the time they matter, the user has already successfully logged in, through whatever number of factors your app requires. A perfectly secured login screen sitting in front of a backend with a missing access rule is still exactly as vulnerable as one with no extra factor at all, once someone's actually inside.
Why this specific confusion happens so often
2FA is visible, it's a real, tangible extra step a user experiences directly, which makes it feel like a comprehensive security measure precisely because it's felt rather than invisible. Access control, by contrast, is entirely invisible to a normal user doing normal things, which is exactly why it's so easy to assume it's been handled once a more visible security feature like 2FA has been added, even though the two protect against completely unrelated categories of risk.
What actually needs both, not either
- Add 2FA. It's real, valuable protection against credential-based attacks and it's worth having regardless of what else you do.
- Separately, and just as seriously, run the access-control checks that make up nearly everything else on this blog: cross-account tests, admin route checks, database rule reviews.
- Never treat one as a substitute for the other. They protect against entirely different categories of failure, and an app can be perfectly strong on one while being wide open on the other.
2FA answers "is this really the person who's supposed to be logging in." Everything else on this blog answers "once someone's logged in, what are they actually allowed to touch." Both questions matter. Answering one well says nothing at all about the other, and conflating them is exactly how a well-protected login screen ends up sitting in front of a wide-open database.