It isn’t just Ruby on Rails login forms that are broken. The majority of login forms on the internet are fundamentally broken.
In what appears to be some form of risk management strategy, these login forms introduce a different risk to the websites that use the default behaviors – in RoR sites, this is often either AuthLogic or RestfulAuthentication.
Both are broken in a big way.
First, the bug. And you might not even recognize it is a bug because the behaviour is so wide spread, so ingrained, and so “sensible”.
On almost every login form, if I submit either the wrong username OR the wrong password. I get the same error message. Usually it’ll be something brief like the following.

Notice the very important word in this message. OR. Because the error message is the same if I enter the wrong user name OR the wrong password, I don’t know which piece of data I entered incorrectly.
I’m guessing virtually everyone reading this is now thinking “well yeah, if you tell them which piece is wrong, someone can keep guessing until they get it right.”
Before we get into that, what are the risks being mitigated in this process? You don’t want someone to hack into one of your user’s accounts, right?
Right.
But what else? How about the risk that someone, a new user, comes back to your site and has forgotten which password they are using? Maybe you forced them to use some complex password. Maybe not. In any case, maybe they want to use your site, but it isn’t really that important. As web app builders, we’re constantly thinking about lowering the barriers to join and begin using a web application, right? Why would we add a barrier here. It is possible that a user with difficulties signing in might just leave. Never to come back. Never to pay you for your service.
All because you were not kind in telling him/her why the credentials they gave on login didn’t work.
So, that’s a risk. And for a startup, this is a significant risk. You need every new user you can get. Especially those people that have taken the time to actually create an account.
But let’s get back to the “common sense” reason for not telling the user more about why their credentials didn’t work.
You may notice on the signin form above, that link to “Forgot“. If you click that link and enter a user name (email address in this case), the system will almost always tell you if that user name exists. Using the above site, it’ll look like this.

So, lemme just repeat the problem.
Login forms almost never tell you if your user name is wrong
Compared with
Forgot password forms almost always tell you if your user name is wrong
So let’s get back to that risk that is supposedly being mitigated by not telling the form submitter what piece of data is wrong. We’re trying to keep people from guessing user names, right? And yet we provide a form for doing exactly that!
The risk is not mitigated in the slightest by the error message. Not one bit.
Now, I’m not going to go into how this process should be done. For two reasons. One, I’m out of time for writing this morning. And Two, because I want people to disagree with me so I can understand their thought process. It is possible I’m missing something here. Unlikely, but possible.
You’re right, it’s revealing too much information if that amount of security is more important than usability. It’s all a usability/security trade-off. What it mitigates in the forgotten password form is user confusion and support requests when the person enters their username or email wrong and therefore the our forgotten password form is broken. It’s a small trade-off but may not be worth the security risk depending on the application.
Hey Nate,
What I’m getting at is there isn’t actually a trade off. If you think you’re implementing a security measure through obfuscation in the login form, but you provide that same information in the forgot password form, then the only thing you are doing is irritating your users. No security/risk mitigation has been implemented.
Unless I’m missing something, which is totally possible.
I agree, it’s inconsistent.
It’s helpful to analyze the supposed risk that someone will hack into a user account:
1. They may already know the username (because they’re targeting a specific person). In this case, obfuscating the error information doesn’t mitigate the risk.
2. The hack attempt is automated and is based on a high volume of attempts. This is what things like Authlogic::Session::BruteForceProtection are for.
3. I assume banks have to worry about this problem more than just some random website. What do banks generally do? Nowadays, they seem to make the login a two-phase process: username first. Presumably, the result of entering a non-existent username is different than the result of entering an existent one. That’s probably the best evidence so far that obfuscating the error information in a one-phase process is a questionable mitigation.
Schneier’s article provides some interesting food for thought on people’s intuition about risk:
http://www.guardian.co.uk/technology/2009/aug/05/bruce-schneier-risk-security
Thanks for the comments Mark. And thanks for that link. I like this quote from that article.
“They know what the real risks are at work, and that they all revolve around not getting the job done. Those risks are real and tangible, and employees feel them all the time.”
Totally agree! In most contexts anyways…
However, there’s an even deeper rant that I have… Just use OpenID! Let another service worry about authentication issues. That shouldn’t be your app’s concern. Slap on something like https://rpxnow.com/ and be done with it.
This is wishful thinking, though. It’s the thinking of a programmer who’d rather outsource this nonsense and get to the real meat of the app.
I’m aware that you’ll probably just lose a ton of customers who can’t figure out OpenID. But it’s my dream of convenience that one day, every web app I sign in to is just OpenID.
Great point Jon.
We’re definitely closer now than we were a year ago. There are getting to be more systems that people are signed into all the time. Outsourcing authentication to those other sites where people are almost always signed in, to automate authentication for your site – where your users are probably almost never signed in – is the way to go.
With the latest funding for JanRain, we’ll probably see many improvements in the coming year.
But for now, as a site owner, I get a bit nervous about my user’s understanding that process. Looking forward to when this is no longer an issue.
The reason for the ambiguous error message may not be just security. Consider two users: John123 (password: “abc”) and John124 (password: “def”). If I enter John123 and “def”, how do I know which is wrong. It is a valid password for somebody, and it is a valid username for somebody else. All I know is that the two do not match, so I tell them that one of them is wrong. It is not about security at all, it is about my inability to distinguish which field is wrong.
Hey Craig, thanks for the comments.
All systems for logging in that I know of do not enforce uniqueness among passwords. It would be a strange constraint on a user’s password and I think there are enough of those already. (passwords gone wild)
So, you could never reliably look up a user by the password entered. The only choice is to first look up by the unique token (email address, user name, whatever) and then make sure the password entered matches the password stored. (I’m simplifying, we shouldn’t store the original password.)
With this said, your example doesn’t actually cause a problem. “def” could be the password for multiple people and it is simply ignored because we can make no claims with the paucity of information it contains.
On the other hand, because user names are forced to be unique, we can very well assume that if a person enters John123, they intended to sign in to that account.
It still comes down to an incomplete or misguided notion of security by the developers of the common rails authentication gems.