Earlier this year, a post about best practices for user accounts and authorization was published in the Google Cloud Platform Blog. This topic has interested me for some time, so this is my own take to the topic.
1. Require long passwords
You can even label the input “secret words” to encourage your users to write something easy to remember (for them) but very secure at the same time.
These day, however, depending of your users, many of them might be using a password manager anyway (1Password is cool btw), so don’t be afraid of requiring passwords of at least 16 chars long.
2. Be flexible (the real world is messy)
You probably haven’t noticed it, but Facebook let you sign in even if your password is not precisely the same. It’s true, but don't panic! Their password validation is designed for those cases when you think you have written the right password but you really haven’t.
If (the hash of) the password you try is not the same as the one you registered with, it tries the following, in order:
It’s a clever way to reduce the calls/emails to support (“Help! I can’t access my account”), specially when you have a billion users. I think is worth considering, even if you don’t.
3. Be flexible, part II
Do trim any leading spaces in the username/email too. My phone autocomplete insists on adding one at the end.
4. Usernames are useful...
An email and a password it’s all what you need to authenticate right? Except that the moment you start adding something “social”, like a public page, an username will be very useful, even if only to have it in the URL instead of the user_id. And it’s easier to requiring in the sign-up form, instead of dealing with asking for it later.
5. …but working emails are indispensable
The email is one of the most important means of communication between your site and its users. Even if it’s used just for resetting the password, you better make sure it really works.
The least you can do is to use a service to validate that the email exists (not only that it looks like a valid email address). You can even do before accepting the user’s registration. This will catch many of the cases when the user writes their email address wrong.
A double opt-in — meaning requiring the user to “activate” their account by clicking a link in an email you send — is advisable, but since is extra work, might scare some users, so is your call to do it or not. You can also not requiring at first, but asking for “email confirmation” before allowing your users to do certain actions.
6. Make user logins case-insensitive
Your users may not even remember the exact case of their username/email. Forgetting their original capitalization shouldn’t be never reason to preventing them to sign in to their accounts.
Some users, however, do care a lot. So don’t just lowercase it before storing it in the database. Store them as-is and lowercase them on-the-fly when comparing usernames.
7. Allow users to change their username
Use a common auto increment integer as primary key of the users table and this shouldn’t be a problem.
Depending of your application, there might be some security concerns like a user impersonating another by talking their old username… but there are ways around that, like reserving the last-used username in addition of the current one.
8. Hash those passwords
You already know this, right?
Never store passwords, just the result of salting and hashing them with specifically designed algorithms for password hashing. The current winners for this job are PBKDF2, Bcrypt, or Argon2. What make them so special? The fact that are super slow — and can be made even slower — and thus an offline brute-force attack (using a program to try all possible combinations of letters/numbers/symbols) takes forever.