Application developers usually tend to be as much specific as possible when providing information about unexpected errors occurred during runtime. For most of the time, this is a good approach to do so, but not for all use cases. User login scenario is among one of those exceptions. When a user provides insufficient/invalid credentials, or when a user account is inaccessible because of some other reason, application shouldn’t reveal more information than he/she isn’t allowed to login because of invalid or insufficient credentials. Otherwise, provided information might be revealing too much information about current status of the user. Let’s look at the following code example;
UserDetails userDetails = userDAO.findUserByUsername(username); if(userDetails == null) { throw new UserNotFoundException(); } else if(!userDetails.getPassword().equals(password)) { throw new InvalidCredentialsException(); } else if(userDetails.isRevoked()) { throw new UserRevokedException(); } else { return userDetails;
}
The above code block tries to identify possible causes of unsuccessful authentication attempt as much as possible. Actually, it is good as long as the identified cause isn’t bubbled up to the GUI, with error messages like; “You cannot login. Username not found.”, “You cannot login. Invalid password.”,”You cannot login. User revoked.” and so on. With the help of such descriptive messages, a hacker trying to attack against your system might deduce some critical information for his/her break-in attempts. Instead, a general “unsuccessful login-try again” message should be enough, for example “Unsuccessful login attempt. Invalid username or password.”
My opinion about why many application developers fall into that trap is that, apart from not having enough knowledge about application security concepts, they simply confuse such business exceptions with unexpected program errors, and try to provide current user as much information as possible to help them with identifying what did go wrong at runtime. For our case, catching a general AuthenticationException in presentation level, and showing off the not so specific “unsuccessful login attempt” message should be the way to go.