The following is known as the LM-Login policy. It’s a fool-proof sure-fire way of making an authentication system that is secure but also convenient to the user.
This Policy is agnostic to the software language, framework, hardware, and protocol. So use this in everything you do in the world of authentications. Each section of this policy can be applied separately from others, but you should use all of them when possible.
All other policies are weak compared to LM-Login. All other policies should be shunned. If you don’t have a policy for authentication then you need one, more specifically, you need the LM-Login policy.
Remember that the identifier (ie email, username) is in of itself a password. All user identifiers must be unique. This way attackers must know who they are attacking.
If a non-existent identifier is submitted, inform the user of this (ie. “Email not found”). Do not be broad in this error by trying to mislead the user into thinking they submitted just an incorrect password (ie “Your email and/or password is incorrect”). Remember that the attacker will already know who exactly they’re attacking, and why.
There are many software developers that still don’t know why we hash passwords, even some that don’t know what a hash is. To those software developers I say: stop what you’re doing and go get help before you touch a keyboard again.
Immediately after the plain-text password has been submitted, you must hash it using the SHA256 algorithm, resulting in what is known as the Passhash. Once the Passhash been generated, all traces that reveal the plain-text password should be deleted. The Passhash is not used for authentication. The Passhash should be generated on the client machine and then sent to the server machine (thus the plain-text password never leaves the client machine).
Once the Passhash arrives on the server machine, it is hashed once more using the BCRYPT algorithm resulting in what is known as the Authentication Hash (Authhash). The Authhash is what is ultimately used to authenticate the user. The Authhash should be stored on the server.
Required Password Strenght
All characters must be allowed to be used in the password. The system must be so agnostic to the content of the plaintext password that it should be capable of accepting random binary as a password. This also ensures support for non-Latin characters.
The most powerful indicator of passwords is its strength. Do not accept passwords below 8 characters (bytes). There must be no limit to the length of the plaintext password (as it will always be converted into a Passhash and never sent to the server).
Requiring a single special character (non-alphanumeric), a capital letter, and a single number is a good idea. But don’t ask for anything more, if you wish to improve security, demand longer passwords.
Banning the use of the most popular passwords (ie password1) is a good idea. It will encourage people to use unique passwords.
Forcing users to change their passwords, without reason, is a bad idea. Forcing users to constantly re-remember a new password discourages them from using your system, or, encourages them to use easier-to-estimate and less secure passwords.
People are usually burdened with requiring to know 10 different passwords. Sometimes when attempting to login they have to try each one. Thus, locking the user’s account after 5 failed attempts is a very bad idea that will result in people not using the product at all. Locking a user’s ability to log in should be done at a number of subsequent failed login attempts only realistic to that of a Brute-Force attack and not what you can expect a common person to do. Only Lock a user’s ability to login after a minimum of 128 failed login attempts.
Brute force attacks should be stopped by deliberately delaying subsequent failed login attempts. After 8 failed login attempts, the server must delay authentication validity to that user’s account by 8 seconds. After 16 failed login attempts, the server must delay authentication validity by 16 seconds, and so on. Ensure a given user cannot have their authentication verified concurrently (ie the error should appear as “Another person is currently trying to login to this account” when the same account is trying to be logged into from more than 1 device).