You should verify a user's second factor before password.
You should verify a user's second factor before password.
Most services today have fairly low "lockout" + "notify" thresholds on wrong passwords so brute force spraying passwords is already out of the question.
Now, if someone fails the password check, clearly the user's current password is still secure so leaking that the attempted password was wrong to an attacker is not particularly helpful to them. If, however, the password is correct, then the attacker gets hit with the 2FA surprise. Assuming the great suggestion in this post is implemented (it really should be), the attacker now is stuck--abandoning the login or trying an incorrect 2FA could all trigger notifications to the user that their password was breached [re: the "Was this login you?" prompts implemented by major services after these situations]. Attackers would need to also solve the 2FA in some reasonable period to "disarm" such an alarm.
Real users who happen to fumble once or twice are also fine, since they won't be surprised about the login confirmation as it really was them.
Maybe I misunderstand your post, but I think the parent comment is talking about leaking whether a password is correct and not whether it's wrong. (If I did misread your comment, apologies in advance and disregard the rest.)
The parent comment is basically suggesting that if there are two possibilities for password entry with two different experiences, then we may be telling hackers that passwords are correct, too.
Scenario 1: Password is incorrect and user sees "Oops, wrong password!" message.
Scenario 2: Password is correct and user sees 2FA prompt.
You are correct in that Scenario 1 doesn't help the hacker -- but Scenario 2 does! It tells them that the for username jabbany@email.com, password hunter2 is a valid password. Even if they do hit the 2FA surprise and can't crack it, they can now take jabbany@email.com to any other website and try password hunter2, and any other site using the same credentials that is NOT secured by 2FA is now compromised!
There's also username leakage here. Imagine you had an OnlyFans account, and your coworkers or friends or parents were to put jabbany@email.com into it, and it simply said "Oops, wrong password" instead of something more generic. Now they know you have an OnlyFans account -- which, depending on your relationships, could be problematic, regardless of whether they actually accessed the account.
So to the parent comment's point, it is amazing how often credential leakage happens. And to OOP's point, we should go to 2FA every time, whether the credentials are correct or not. And the error messages should (generally) be more vague than specific, so as not to leak info unintentionally.
Does that make sense? I'm not sure I explained it very well, but I think the parent and I are making a different point than yours -- which is also a valid point, just not what we were talking about.
So you’re asking for the business to implement something that makes their own users less secure so that sites that don’t provide 2fa can be more secure. Maybe it would be better for those sites to improve their own security instead of asking others to compromise theirs to help cover for someone else’s lack of effort.
The leak of the password's correctness here is ultimately not problematic as it acts as a tripwire and a surprise for the attacker. In fact the platform can take action on the user's behalf and lock logins with that password until the user confirms it was them trying to login via a separate channel (if you used Google 2FA this is what they do). It also protects accounts without 2FA because it becomes risky for the attacker to just try a password list they find. Maybe they're lucky and get in, or maybe the account has 2FA and you've just burned the password by trying it and alerting the user/platform about the compromise.
If it were the other way around with 2FA first, you would have no way of knowing your password is compromised somewhere. Even if the attacker knew the right password, the would not attempt to login unless they defeated the 2FA. Now you have no early warning system, and it becomes all-or-nothing: attacker get full access or they wait silently.
To sum it up: The login is no weaker if you put 2FA after password auth (same amount of compromises needed to get in). 2FA after password can leak password validity information for a short duration of time (on the scale of 15mins), but it also sets in motion an alarm that invalidates that password when an attack is attempted. 2FA after password also provides a tiny bit of extra protection to non-2FA accounts by letting them hide among the 2FA ones.
(Also, the original purpose of 2FA after password is to cut down costs for the platform back when SMS 2FA was the only 2FA. This is largely irrelevant today with TOTP and FIDO2 relegating SMS based authentication as the least secure option.)
I'm not concerned about someone hacking this site with the 2FA tripwire, but instead about leaking password's correctness could impact usage of that password on other sites that use the same username/password and do not have 2FA.
Imagine if I go to Amazon and put in jabbany@email.com / hunter2 and then come up against a 2FA prompt instead of a password error prompt. Okay. I have a signal that suggests that hunter2 is, in fact, your password. I bail immediately. No point in randomly trying to guess a 2FA auth code.
Now I go to Walmart.com and put in jabbany@email.com / hunter2, and it works -- because there's no 2FA on Walmart.com and you re-used the password!
In this scenario, 2FA doesn't actually stop the hacker from compromising your accounts! It only stops this account with 2FA -- in that sense, you are 100% correct! -- but perhaps only temporarily, because they may be able to compromise other accounts that would allow them to eventually reset your 2FA tokens and get through.
If Amazon were to tell me "hey, someone failed the 2FA auth attempt, you should you change your password," then that's one thing. But we both know most sites don't do that.
This does not make reuse more dangerous either. An attacker with a leaked password list will try them against known sites anyways. If they wanted to try a leaked password against Walmart they'd have done it regardless of the 2FA signal. There's no reason to assume that if a password is (in)correct on one site that it would (not) be on another. The information of whether a password worked or not on a site means nothing to someone trying to hack your account.
Also 2FA sites do do this already. Google and Amazon both do this along with many others (and increasingly many). Also it does not have to force a password reset. A notification email about an attempt is sufficient, you can decide for yourself whether it was you or a suspicious attacker.
Personally I don't know enough to know if that's the case?
So all this discussion about how to handle the failed login is somewhat pointless.
1. Users who aren't using 2FA have a confusing box to leave empty.
2. SMS, Email and similar OTP codes should only be sent after the password is verified.
3. U2F requires the site to share which devices are registered which can only be done after the password is verified.
You may be able to make it work UX-wise if you separate username from auth information (such as a lot of sites do to support SSO auth). But even then it isn't clear to me if you should be leaking information about their 2FA configuration (especially their U2F device) list without a password.
For example, given this /login request to our server:
POST /login
Authorization: Basic Zm9vQGJhci5leGFtcGxlOmJhego=
Depending on the user's second factor, the server could send back a response like this: { "error": { "code": "TOTP_REQUIRED" } }
Then, depending on the error code, our UI could prompt for the second factor and we could send a new /login request: POST /login
Authorization: Basic Zm9vQGJhci5leGFtcGxlOmJhego=
{ "totp": "123456" }
This flow can work for any type of second factor, not just TOTP. It also works for good and bad passwords, and doesn't leak any information (well, other than the fact the user exists, but that road introduces a lot of other UX issues.)It does leak a little information. It leaks the type of 2FA the user has configured and a list of devices for U2F (since that needs to be provided to authenticate). But that is likely acceptable.
the cost of sending those 2fa texts is not zero and also the idea of them is that they are ephemeral so them being tied to the successful entering of username and password and limited in time is a feature... not a bug.
Errm, could you elaborate what is the issue here?
Consider this, scenario A:
1. When attacker enters a username and bad password. then they receive a bad password error.
2. When attacker enters a username and good password, then they receive a 2FA prompt.
And then scenario B:
1. When attacker enters a username and bad password, then they receive a 2FA prompt.
2. When attacker enters a username and good password, then they receive a 2FA prompt.
In scenario A, the website leaks password validity to the attacker. In the case of a brute force attack, the attacker can use the 2FA prompt as a signal that they found a good password. Scenario B does not leak that information, because the second factor was wrong or missing.
More concretely, this pseudo-code:
if user.authenticate_with_password(password)
if user.authenticate_with_second_factor(code)
# ...
else
raise InvalidSecondFactorError
end
else
raise InvalidPasswordError
end
Should instead be this pseudo-code: if user.authenticate_with_second_factor(code)
if user.authenticate_with_password(password)
# ...
else
raise InvalidPasswordError
end
else
raise InvalidSecondFactorError
end
Hope that makes sense. :)If MFA can be configured using myriad choices, should a user be prompted to "Insert security key" or "Input security code" or "Send code to your email/SMS" or "Tap YES on your mobile device"?
Since you can't know a priori what the second factor will look like, I'd say it's troublesome to try and present a challenge to every user regardless of their MFA configuration.
If your 2FA options all require the user to enter a code, you can simply display a "Please enter your 2FA code" dialog without divulging what kind of 2FA the user has.
An attacker brute-forcing the password could flood the user with multiple messages. The usual response is doing a password reset, but that wouldn't work in your system.
I wonder how systems that use magic links handle this.
Wasn't something like this how Uber got hacked recently? Spamming the target until they clicked "yes" on the 2FA prompt?
The UI could then use these error codes to display the correct prompt, and then resend the request with the appropriate second factor.
If you input the right username and password, it will then go forward in the flow and prompt you for the 2FA.
I believe parent comment is suggesting the system should prompt for 2FA even if the password was incorrect, so that you can't infer whether you guessed the correct password without also compromising the 2FA method.
This only matters if you re-use passwords, though.