Whenever we work on user authentication, we need to deal with passwords and storing them in the database. For security, it is important to save passwords securely in our application database.
But many times we feel confused on this topic. Especially we try to choose the best way to store those passwords. Because there are a few important steps you must follow to make your application secure.
By going through this article you will learn the best practices for securely storing passwords and some bad things that you must avoid. You can also use this technique to save passwords using Node.js and Express servers.
Don't Store Passwords As Plain Text
When users signup for a website, they submit a form with different information like username, email, password, etc. We save those details in your database.
But you should not save the password as plain text like other information. Because if our database gets compromised, a hacker can easily see those and use them.
That's why we have to hash our passwords before saving them in our database. Even if hackers get access to the database, they won't understand the passwords. Instead, they will see some random useless characters.
Key Terms Related to Saving Password
Before going through the process you should understand some key terms related to this topic. This will help you to understand the steps easily. These terms are:
- Hashing: It's a process of converting a text into another random value using a mathematical algorithm. Anyone can't guess the original text by seeing that hash value.
- Salting: Salt is a random unique value. We add salt to the password to generate a more unique hash value. This process is known as salting.
In our next few steps, we will discuss hashing and salting in detail. Like how to do these and the most secure way of password hashing for your application.
Also Read: Cookies VS Local Storage VS Session Storage: Usage and Differences
Hash Password Using One-Way Hash Function
To generate a hash value from a text, we use a hash function. This is also known as a one-way function. Because once we hash a text or in this case a password, we can't get back the original text from that hash value.
There is a process called Encryption which also takes a text and returns a random string like hashing. But we use a private key to encrypt some text. Using that private key, we can also decrypt the random value to get back the original text.
This is the main difference between encryption and hashing. If we encrypt our password with a private key, anyone will be able to decrypt using that key to extract the original password.
Encryption is not a good choice for this reason to safely store passwords. That's why we will use hashing function.
Best Hashing Function For Password
There are many hashing functions available to use. But we need to choose carefully. Because not all functions are suitable for passwords. We usually consider a slow function to generate the password hash.
If you choose hashing functions like MD5 or SHA1, our application will be vulnerable to Brute force attacks. It's a process of submitting many passwords one after another to find out the correct one.
These functions are very fast. They can generate and compare millions of hashes within a second. That's why we use functions that are slow and resource intensive. Therefore attackers can't use a brute force attack on our application.
Not only that, we should use rate-limiting so that one user can't make too many within a given duration. If they try to send many requests at a time, the server will block these and won't process them.
Now the question is "Which hashing function should we use?"
You can use functions like Argon2 or Bcrypt to generate the password hash. You can read more about the difference between these 2 functions here if you want.
Both of them are slow in calculation and resource intensive. These make them more suitable for password hashing.
Also Read: Redirect HTTP to HTTPS Complete Guide using Nginx, Apache, htaccess
Add Salt to The Password
Only hashing a password isn't enough for security. Even though attackers can't unhash to retrieve the original value, they can use another technique to identify passwords.
Sometimes attackers may have a huge collection of commonly used passwords and their hashes. This type of collection is known as a Rainbow Table. Therefore, they can use "Dictionary Attack" to compare our hash value with their rainbow table.
In this example, you can see if someone compares password hashes against the rainbow table, John's password hash matches. Now they know John's password is "Abc123".
But if we add salt (random value) to our passwords, we will get unique hash values. Now even if John uses "Abc123" as his password, the hash will not match with the rainbow table.
Because hashes in this rainbow table didn't include the salt. There is another advantage of using salt while hashing. If other users use "Abc123" as their password, their password hash will match John's hash.
The same password will generate the same hash value. Storing the same hash multiple times is not a good idea. When we use different salt for each user, the hash function will generate totally different hashes even if they use the same password.
It is very easy to generate and add salt to a password. When users try to sign up, they provide passwords. We have to generate a random unique salt for each user and add it at the end of the given password.
Now we can pass the whole thing to a hashing function. It will give us a hash value for future use. In this way, we can use salt in our user authentication system.
Also Read: Easiest Way to Set & Use Environment Variables (.env) in Node.js
Store Generated Hash and Salt in The Database
When we generate a hash value using a password string and a salt, we also have to store them in our database. Because when a user tries to log in with a password, we need to use the same salt to check whether the password is correct or not.
That's why we have to store both the hash value and the salt in our database. So that we can hash the password that users give during login using the stored salt and compare it with the stored hash.
How to Compare Passwords While User Login
We have seen the technique of hashing and storing the password in our database. It is also important to know the process of comparing passwords. Otherwise, users won't be able to log in.
You know we can't retrieve the original password from a hash value. Therefore, to check whether a user is giving the correct password or not, you have to follow the same process of hashing.
We will get the salt and the hash value of that user from our database. Then add that salt to the given password and generate a hash using the same hashing function that we used during sign-up.
Now compare the generated hash value with the hash we stored in our database. If both hashes match, that means, the user is giving the correct password. We can allow this user to log in.
If the hashes don't match, the password is incorrect. We will ask the user to provide a correct password in order to log in.
Bad Practices For Storing Passwords (Don't Use)
We have discussed the way to store passwords. These are some bad practices we should avoid for better security:
- Never store passwords as plain text in the database.
- Validate passwords and ask users to use strong passwords.
- Always use a slow and resource-intensive hash function while hashing.
- Add unique salt to the password and store that salt value in the database.
Also Read: Node.js Cluster: Improve Server Performance with Clustering
User authentication is a very important part of an application. If we don't follow the correct process, we will have the risk of getting hacked. That's why you need to store user passwords securely.
You have seen the good practices that we should follow and some bad practices that we must avoid for security purposes. But if you don't want to handle passwords, you can use other authentication services like Google or Facebook for user authentication.
Most applications use external authentication services as well as their own system for user sign-up and login. That's why we should know the best way to securely store passwords in a database for user authentication.