“Username or password is incorrect” is bullshit
hackernoon.com
hackernoon.com
First, you should define your threat model: which information is considered secret and which isn't, and treat any violations as security vulnerabilities.
If usernames are public by design, then don't hide them in one form, and expose in URLs elsewhere on the site.
If exposing who's registered on your site really is a threat, then by all means have a weird registration (and password reminder) that doesn't tell whether it worked or not. But if your site is for cookie receipies and you don't consider exposing who's a fan of cookies a privacy violation, then just use most helpful messages you can.
Unfortunately, when designing a login flow (and a signup one), you can’t assume that the user always inputs the right things.
Try logging in into facebook, for example, mistyping gmail or with your password with the wrong case, like all uppercase. In many cases... you get in! This is to prove that they had to “improve” their flow to account for wrong user input.
Because user input can be wrong in both email or password, the error message should account for both.
Obviously, Github and Stripe aren't actually enforcing these messages as part of some larger security policy, or if they are, they're doing it very poorly. But if they were, the email shuffle is what they ought to be doing.
My short gmail address gets a signup on some random website a couple times a month and they're often nigh unto impossible to delete.
Fitbit is one of the worst for this.
Might as well let a user logging in that the username is incorrect to make the legit use case, i.e. user has a typo and/or misremembers their username, more pleasant.
I usually suggest clearing the username field on failed logins as well. That way if there is a typo, the user doesn't try it again thinking only the password is wrong.
Default to knowing your threat model. Default to balancing security concerns with UX, and make an informed decision instead of blindly following best practices.
That’s an easy way to be targeted.
It is the intended user, but the password is wrong
It is the right password, but the user is mistyped
The login screen has no way to know when is one or the other.
The OP wrote a whole article based on the wrong assumption, and since the title is a click bait, it made it to the front page of hacker news.
Sad.
Seems wrong, somehow.
(Not that any of this is good practice.)
Most likely on this part: a good password hashing (ie. security hashing) should be fast so that you can log-in but slow enough to prevent brute force (ie. what you are implying). Hashings like md5/shaX don't have that: you can compute of lot them very quickly, which is their purpose. Bcrypt/Argon2/... will have a cost/time that will allow only a few computation per second, which is their purpose.
So if you did best practices well, and try to loop through your users database, (I assume you have more than a few hundreds users) it might take some time, some long time. Anyway, you'll then fail at another best practice because the initial user trying to log in will get bored and be gone somewhere else ;-)
Also it's technically possible to check the password against all other passwords, it just requires rehashing it for every user in the table, you shouldn't do it obviously.
edit: Even if you would check it, it wouldn't help to answer the question about whether the password or the username is wrong, even if the password is used for a different username you still don't know that it's the right password. So it's a bit strange that it is brought up as an issue that you can't check against other usernames.
A system that used an "existence" or "user intended to type this" concept of password correctness would be either unimplementable or insecure to the point of uselessness.
So for login: always say "email or password is incorrect".
And for register: as he said, always say "we sent you an email to verify your email".
Making your validation errors cross mediums and a wait for an e-mail to delivered is an unnecessarily hostile user experience.
One problem with that is that when users are given the option of an arbitrary username, they tend to be much more likely to forget that username than they are the email address they use daily. So, you need some way of resetting their password and letting the user recover their username. In some cases, you could pair that with other identifiers, like their name, phone, social security number, etc. However, then you are just trading the email as an identifier for something else, which you would also need to check during registration.
For this reason, I've found that moving away from a username and just relying on an email for a login makes managing multi-user sites a great deal easier from an admin side.
I agree that e-mail makes for a better login experience, but if exposing who uses your site is too much of a privacy concern, I'd rather move to usernames than have to implement awkward user experiences to never reveal whether someone is a user or not.
Although to the point of this article, they will then happily tell you you can't use an email during signup, so it is a mixed-bag.
I suppose if you allowed multiple usernames per email, you could just email them all the usernames that they have on that email address when they forgot their username, but that seems like a clunky setup. It probably depends a lot on the service though, as someone posted a link to a discussion from 2014 about Amazon's reasoning for allowing multiple emails elsewhere in this thread, which makes a bit of sense for their use-case.
Say I've got a leaked password database for foo.com and know that the user bob@gmail.com uses the password "tomato1". If I try using his credentials to log into bar.com and get the message "username or password is incorrect", I'm just going to try the next user on the list. If I get the message "incorrect password", it makes sense for me to try "tomato2", "tomato3" etc. If I know that your password policy requires eight characters and a capital letter, I'm going to try "Tomato11". This is obviously trivial to automate.
You can't protect your users against credential-stuffing attacks if they use the same password everywhere, but you can offer them a small layer of protection if they use the same password with minor variations.
As others have pointed out, mere disclosure of the existence of an account could be a serious privacy breach in itself.
1. Identify people who are gay/bi (e.g. signed up to grindr)
2. Identify political affiliations (depending on site)
3. Identify health issues (signed up to a mental health forum, or cancer support group, etc)
These things people might be happy others knowing, but I hope you can at least see some cases where you might not.
Suppose another website has a security breach, revealing many names and passwords. User John Doe used a password of "foo", so an attacker starts trying combinations like jdoe/foo or johnd/foo or john_doe/foo, looking for the same person reusing a password on your site.
By denying them information about which login names exist, it's harder for the attacker to either zero-in on the correct username (and try alternate password variations) or to be certain that they've got nothing and that it's time to move on.
You could argue it's security through obscurity - I'd say preventing leaking data.
"email or password is incorrect" is bullshit is right.
Given that, who cares what error message you display, as an attacker I only need to be able to find out weather a system has an email or not, and the sign up screen is a perfect oracle.
For this I would recommend adding the mention "your username will be publicly visible" during the registration process.
It would be next to impossible for an attacker to bypass that. For example, even if the attacker provided the correct credentials, they most likely would not have the associated client-side TLS certificate private key. Then the server could just reject the log on attempt outright (since the certificate wasn't provided or verified).
I don't think that's good practice. What's better is to have a separate key/certificate per device that's used to access a service. That way, even if one machine is compromised (or stolen), then the user can still use other devices to log in. Also, the service provider can disable certificate log in on a per device rather than a per account basis.
> Also, if you don't have the private key with you, there is no way you can log in to the site.
That's not necessarily true. Some HTTP server software (e.g., nginx) do have the option of requesting/asking for a TLS client certificate rather than requiring one. If one is not provided, then it's still possible to connect and log in. Server side policy can be much more strict in terms of locking the account in case of incorrect credentials or restricting access to certain account features if the client certificate wasn't provided.
Private keys and certs aren't as portable as passwords. Backing them up, copying them to another device, etc. lacks good UI.
U2F is the modern re-do of client certs.
Of course the person may have multiple user accounts and he may have given the "wrong" password for the "right" username account, but he may also have given the "right" password for the "wrong" username.
You could provide the correct password to your account 'test', but not 'ttest'.
The server just tells you to check both instead, it's more semantically correct and offers some security improvements with user enumeration.
Imagine both 'dave' and 'davr' have an account. I'm 'dave', but I accidentally type 'davr' and my correct password. Now the site will tell me that my password is wrong. So I retype and retype my password over and over again and still can't log in, because the problem isn't the password like the error message says, but rather that I typed the wrong my username.
For a rarely used web site, I honestly would have no idea if I registered as bonzini, pbonzini or bonzinip. Now my surname isn't particularly common, but smithj and jsmith might be easily confused.
It is absolutely common for users to supply the incorrect username/email.
Not accusing you BTW.
> To prevent attackers from knowing whether an account exists or not your signup must only take an email address and provide no feedback in the UI if the sign up succeeded or not. Instead the user would receive an email saying they’re signed up. The only way an attacker would know if an account exists is if they had access to the target’s email.
> Barring that, “username or password incorrect” is just bullshit.
What he means is the only way it would make sense is if and only if a website's account registration page responding with something like:
"You tried to sign up for me@example.com. If that account didn't already exist, a registration email has been sent to it."
But nobody does that! Registration pages just say "Sorry that email is already in use", which is what makes this whole thing bullshit.
> To prevent attackers from knowing whether an account exists or not your signup must only take an email address and provide no feedback in the UI if the sign up succeeded or not. Instead the user would receive an email saying they’re signed up.
Is this not also part of the various 'best practices'? (I confess I don't read too many of them!)
Where it gets really interesting is when you perform user enumeration attacks via timing. IE: it takes the server a few milliseconds longer to send a registration email than to not, or it takes the server longer to try to validate a password hash than to lookup a nonexistent user.
1. Email and password for login. Don't tell the attacker which is correct.
2. Email and password for registration. On registration send confirmation email. If user is already register attacker would need access to their email. Access to email is game over.
So now an attacker can't see which users are registered with your service and you've protected your customers privacy.
Extra points if your code is aware of timing attacks.
This opens up a different problem. It should be:
2. Email only for tentative registration. On tentative registration, send confirmation email.
3. User clicks link in confirmation email, which takes to page for setting password. (Alternatively, confirmation email includes randomly generated initial password, user is required to change it on first login). After password is set, registration changes from tentative to confirmed.
If email and password are both included on the initial registration form, an attacker can try to sign up people and some fraction of those people will accidentally click the link in the confirmation email, thereby resulting in some new accounts where the attacker knows the email and password, and the email owner does not know the password.
The attacker could then use that account to post threats, harass people, and so on. If he goes far enough that either law enforcement wants to come after him or someone wants to sue him and the site is served with a warrant to reveal information about the poster what they are going to cough up is the verified email address of the account holder.
That will be followed to the email provider, and from there to the email address holder. The email holder's claims that he never made the social media account are going to sound unconvincing--he clicked the confirm link to make the account!
Remember, a civil suit only requires a preponderance of the evidence, not proof beyond a reasonable doubt. That verified email might be enough to reach that standard.
In a criminal case it would not be enough...but if the matter was serious enough it might be enough to justify a warrant to search the email address owner's place and computer. At the very least that would be very annoying, and at the worst it could uncover things that the email holder does not want brought to law enforcement attention.
Color me unconvinced.
Except on some sites, e.g. dating websites, this is a stupid theoretical security gain that just pisses everyone off. Like requiring numbers in passwords (basically everyone adds a 1 at the end) or making you change passwords frequently.
It's not OK to leak information, even if that information is maybe leaked somewhere else already.
So in some ways I've always thought of this as a privacy concern rather than a security one?
Edit: I guess I'm thinking purely of emails where you don't get availability checkers during sign up.
Few sites remember to anonymize that, which might be the real PSA: in such a case, if you require an email confirmation anyway, just send the "recover password" email internally, but let it look like the regular sign-up flow.
If you don't requite email confirmation, anonymous membership isn't possible (just try to sign up with that account, what is the site supposed to do that looks legit without giving away information?)
In B2B applications where there is no registration form, then the username is probably a secret. In B2C applications where anyone can register, then the username likely isn't a secret. Many of those applications have the concept of "mentions" by username so clearly the username is not considered a secret in that case.
The privacy is worth it.
I understand that a lot of people think this is a security feature, but once upon a time it was the lazy programmers answer when "SELECT * FROM users WHERE username=? AND password=?" didn't return a result.
With proper salts for hashed passwords you now have to find the username, use the salt to hash the password and compare this. If your database allows to hash passwords with a dedicated function it's still the easiest to say username OR password must be wrong.
For emails, you can very easily fake a second signup with the same email and ping out an enhanced verification email "Somebody just tried to register with this address but you already have an account".
Building the username into that flow is harder. That's why I preference not having separate usernames but some people would argue this is itself a bad thing (removing a factor or somesuch).
Either which way, Stripe's approach is broken. That doesn't make the whole idea nonsense.
Why is imperfect reCAPTCHA worthless? Do sign up pages even allow brute forcing of usernames (once validated)?
Is he suggesting to fix sign up pages, or to allow brute forcing usernames on login?
His writing style is dramatic, but the arguments are very weak.
Depending on the service that's being protected, rate-limiting to 5 minutes between attempts, alerting the owner, and assigning them a temporary username seems more reasonable countermeasures to me.
Having a password just increases the odds of a hack by the user accidentally exposing it.
"Your username is incorrect" "Your password is incorrect" "You hit the wammy. Try logging in again."
That way, you never know what's going on at all.
Oh boohoo. Like it's not on the customers side to know which email it is and which password.
And as many have said, one does gain privacy.