2FA why not to ask the code before password

TL;DR Security is hard and making even small changes to the way security protocols work can open up unexpected attacks. While it may seem at first glance like putting the 2FA before the password helps to protect the password, it actually opens up much worse attacks. Let's have a look!


The problem we're trying to solve

According to your question, the problem you're trying to solve is password brute-forcing. This is a bit of a red herring because people crack passwords against stolen or leaked databased of password hashes, people don't brute-force against live servers because things like rate-limiting already do a pretty good job of solving this problem. That said, let's take a look at different types of 2FA and what would happen if the 2FA went before the password.

Code generation Apps

aka Time-based One-Time Password algorithm (TOTP), for example, the Google Authenticator:

Google Authenticator screenshot

I agree with you that I can't, off the top of my head, think of a reason why putting this first would weaken the authentication protocol.

Notification Apps

Some 2FAs are designed to pop up a notification on the phone rather than hiving you type a code, for example the Blizzard Authenticator:

Blizzard Authenticator screenshot

Doing what you suggest of putting this before the password would actually be dangerous because it leads to a denial-of-service attack: the attacker hammers a user's account so that there are near-constant notifications on their phone, either preventing them from being able to use their phone, and / or forcing them to disable the 2FA in order to make the notifications stop (and weakening their account).

SMS Codes

aka sending a One-Time-Password to your phone by SMS.

This has the same problem as Notification Apps in that it leads to an obvious denial of service attack, but it's worse because in some places, phone carriers charge for incoming SMSes, so the attacker can force the user to pay huge cell phone bills.

Summary

Of the three types of 2FA apps I mentioned, your proposal is neutral for one, and detrimental for the other two.

Also, putting the 2FA step first would advertize to attackers which user have enabled 2FA, and which have not. Basically telling them who the easy targets are.

Finally, the notification and SMS based 2FAs server another valuable purpose: an alarm to tell you when your password has been cracked. If I get a 2FA notification that I did not expect, it's time to change my password.

I like that you are thinking outside the box and challenging the way things are. Security is hard, but don't be discouraged from asking more questions, this one was fun to answer.


It's so users who make a mistake don't wait indefinitely for an OTP that will never come.

Imagine the workflow if the one-time password (OTP) came before password. It would look like this:

  1. User enters user name
  2. System looks up user name to find mobile phone number

    a. If user name is valid and phone number exists, system sends OTP

    b. If neither one exists, system sends nothing

  3. Either way, system displays "We've sent a one time password to the mobile phone number associated with your account."

Why "either way," you may ask? Why is the message the same in both cases? See OWASP authentication cheat sheet which tells us:

An application should respond with a generic error message regardless of whether the user ID or password was incorrect. It should also give no indication to the status of an existing account.

Correct Response Example

-"Login failed; Invalid userID or password"

Incorrect Response Examples

  • "Login for User foo: invalid password"

  • "Login failed, invalid user ID"

  • "Login failed; account disabled"

The reason for the generic message is to avoid providing any signals that a hacker could use for user ID farming.

Now let's continue our workflow.

  1. If user entered a valid user ID that has a phone number, she receives the OTP and can enter it.

  2. If user did not enter a valid user ID, or entered a user ID that has no phone number associated with it, the user waits indefinitely.

So now we see the problem. If the user makes a mistake, the system can't tell her she made a mistake, and she will have to wait for the OTP indefinitely. This is different from password authentication, where the feedback is immediate.

This whole problem goes away if the password is checked first. Once the user is authenticated with the first factor, we have already established that the user ID is valid, and it is OK to tell them if they never set up a phone number on the account.

Other use cases are affected too

These other use cases also become poorer UX, or are awkward to implement due to security requirements:

  1. User has more than one phone.
  2. User has switched phones recently.
  3. User has misremembered his user ID
  4. User is in a locked out status
  5. User's SMS inbox is full
  6. Carrier restriction, e.g. SMS limit exceeded or customer in collections
  7. Phone is lost/stolen

That's for spamming reasons.

Doing so allows an attacker to iterate over usernames (mainly, these are publicly available or very easy to guess) so the website will send a lot of useless texts/mails to everyone. Website would then certainly be blacklisted as "spammer".

And this cannot be secured, except by shutting down all logins for few minutes (if you keep spamming only one account, as said in a comment, then you could refuse to send another OTP if one was already asked minutes ago, but this cannot be done website-wise).

Asking for password first blocks this kind of attack, since you would have to know everyone's password too.