Welcome to the first lesson of our course on Secure Authentication & Authorization. In this lesson, we will focus on the critical aspects of secure password storage and authentication. As you may know, protecting user credentials is a fundamental part of web application security. By the end of this lesson, you will understand how to securely store passwords and authenticate users using best practices. This knowledge will serve as a foundation for more advanced security topics in future lessons.
Before we dive into secure password storage, let's quickly revisit the setup of our Pastebin demo application. This will ensure you are ready to implement the security measures discussed in this lesson. Here's a brief reminder of the basic setup:
This code sets up an Express
application with session management and connects to a database using Sequelize
. With this setup in place, we can now focus on implementing secure password storage.
Password hashing is a process of transforming a password into a fixed-length string of characters, which is not easily reversible. The key idea behind hashing is that the same input will always produce the same hash, while different inputs should (ideally) produce different hashes—collisions, where two different inputs produce the same hash, are extremely rare with good hashing algorithms. This property is crucial for security because it ensures that even if someone gains access to the database, they cannot easily retrieve the original passwords.
In this lesson, we will use the bcryptjs
library to hash passwords. bcryptjs
is a popular library for password hashing because it is designed to be computationally intensive, making it difficult for attackers to crack passwords through brute force.
Let's walk through the process of securely storing passwords using the bcryptjs
library. We'll use the provided solution code to demonstrate this:
In this code, when a user registers, we hash their password using bcrypt.hash(password, 12)
. The number 12
represents the salt rounds. Salt rounds refer to the number of times the hashing algorithm is applied to the password. In the context of bcrypt
, each additional round increases the computational complexity and time required to generate the hash. We chose 12
because it offers a strong level of security while keeping the registration process fast enough for users. Increasing the number of rounds improves security but can slow down authentication, so 12
can handle the balance between security and performance. The hashed password is then stored in the database instead of the plain text password.
Once passwords are securely stored, the next step is to verify them during user login. Here's how we can achieve this:
In this code, when a user attempts to log in, we retrieve their stored hashed password from the database. We then use bcrypt.compare(password, user.password)
to check if the provided password matches the stored hash.
It's important to note that you do not need to hash the input password yourself or specify the number of salt rounds during verification. The bcrypt.compare
function takes the plain text password and the stored hash as inputs. The stored hash contains all the necessary information about the salt and the number of rounds used during hashing. bcrypt.compare
extracts this information, hashes the input password accordingly, and checks if it matches the stored hash. This means you should always send the plain text password from the client to the server for verification, and let bcrypt.compare
handle the comparison process securely.
When implementing password storage and authentication, it's important to avoid common pitfalls and follow best practices:
- Avoid Storing Plain Text Passwords: Always hash passwords before storing them in the database.
- Use Strong Hashing Algorithms: Use libraries like
bcryptjs
that are designed for secure password hashing. - Implement Salting: Salting adds random data to passwords before hashing, making it harder for attackers to use precomputed tables to crack passwords.
By following these best practices, you can significantly enhance the security of your application.
In this lesson, we covered the essentials of secure password storage and authentication. You learned how to hash passwords using bcryptjs
and verify them during user login. These practices are crucial for protecting user credentials and ensuring the security of your application.
As you move on to the practice exercises, remember that hands-on practice is key to reinforcing these concepts. You'll have the opportunity to apply what you've learned and gain confidence in implementing secure authentication in your applications. Good luck, and enjoy the exercises!
