Confidentiality. It sounds like you are trying to prevent an attacker from testing a particular email address to see whether it exists in your database. However, your scheme has a hole: it doesn't actually achieve this.
Given an address, say [email protected]
, the attacker can try logging in with that email address 6 times (using some unlikely password). Then, the attacker can try logging in once more.
If the attacker receives a Invalid e-mail address or password.
response, the attacker can infer that this email does not exist in your database.
If the attacker receives a User has been locked out due to excessive invalid logins.
, the attacker can infer that this email does exist in your database.
Integrity. Your method for validating passwords seems fine, and should prevent an attacker from doing a dictionary search on a particular user's password.
It will not prevent an attacker from making a small number of tries at a large number of users' passwords. Suppose that an attacker can somehow enumerate a set of email addresses who have a login with your service (maybe by some clever websearch, or by exploiting the confidentiality breach above, or something; I don't know whether this is actually possible in your case, but let's explore the consequences if it is). Then an attacker can iterate over all of those accounts, and make 5 guesses at the password for each account.
Recent research has found that an attacker who can make 10 guesses for each account will be able to compromise about 1% of accounts. Extrapolating, we can expect that in your situation, an attacker will be able to compromise about 0.5% of accounts, by making 5 guesses at the password for each account that the attacker is aware of.
You can make this kind of guessing attack harder by keeping track of the number of failed login attempts per IP address as well, and temporarily blocking logins from IP addresses that have a large number of failed login attempts. However, this is not a perfect defense (an attacker with a botnet can easily circumvent this).
Availability. It would be easy for an attacker to lock out a targeted user: all the attacker has to do is try logging in 6 times with an unlikely password, and now that user won't be able to login without contacting your support team. This might be an acceptable risk. The good news is that if this happens frequently, you will know it, and you can put in place defenses at that point.
Standard solutions. You asked if there are any standard solutions. As far as I know, there are no standard solutions. However, in a related vein, you might be interested in this academic paper, which tries to avoid use of popular users: if too many other users have chosen the same password, new users are not allowed to use it. The paper has some clever data structures to make sure this doesn't create new security problems.
Invalid e-mail address or password
even after 5 failed attempts. I suppose that does provide a hacker a way of checking if an account e-mail exists. Is there any risk there?