Welcome to a lesson on how to implement strong password security using the bcrypt library.
By now, you understand how critical it is to store passwords properly.
You know about hashing, salting, and why it’s a terrible idea to write your own hashing algorithms.
In this tutorial, you’ll learn how to use bcrypt in a Node.js environment
to salt and hash passwords, as well as compare them against user input for authentication.
You will learn how to:
bcrypt is and why we trust it for salting and hashingbcryptjs packagebcrypt.hashSyncbcrypt.compareSyncAlthough you grasp the concepts of salting and hashing, it’s never advisable to roll your own cryptographic functions. Think of a home cook trying to invent a new pasta noodle from scratch—fun, but risky for restaurant-grade reliability. Similarly, writing your own hashing algorithm is error-prone and dangerous for production security.
bcrypt (pronounced “bee-kript”) is a battle-tested algorithm for hashing passwords, automatically handling salt generation and including features to slow down brute-force attacks by adjusting the “work factor.”
In Node.js, we’ll typically use the bcryptjs package, which implements bcrypt in pure JavaScript.
Let’s get started by installing bcryptjs:
npm install bcryptjs
Once installed, import it in your code:
const bcrypt = require('bcryptjs');
This sets us up to generate salted and hashed passwords, as well as compare them during login.
Think of bcrypt as your personal guard who does the heavy lifting of password transformations.
To create a salted and hashed password from a plain text input, you can use:
const saltedAndHashedPassword = bcrypt.hashSync(plainTextPassword);
This single method does all the magic:
plainTextPassword.
You can optionally pass a second argument to hashSync to specify the cost factor
(e.g., 12 for extra security). A higher cost factor means the hashing takes more time,
slowing down potential brute-force attempts.
Example usage in code:
const bcrypt = require('bcryptjs');
const plainTextPassword = "catsanddogs";
const saltedAndHashedPassword = bcrypt.hashSync(plainTextPassword, 10);
console.log("Plain:", plainTextPassword);
console.log("Salted+Hashed:", saltedAndHashedPassword);
This saltedAndHashedPassword is what you store in your database.
Like we said before, never store the plain text password; store the salted+hashed string.
Next comes authentication. When a user logs in, they provide their plain-text password. You retrieve the stored salted+hashed password from the database, then let bcrypt compare them:
const isMatch = bcrypt.compareSync(plainTextPassword, saltedAndHashedPassword);
if (isMatch) {
// The user typed the correct password
} else {
// Invalid password
}
Under the hood, compareSync repeats the hashing process with the stored salt
and checks if the resulting hash matches what’s in your database.
If they match, you’ve validated the user’s credentials.
Let’s outline a quick scenario to see how these pieces fit together. Imagine you have an Express route for user registration and one for login.
// registration route
app.post("/register", async (req, res) => {
const { email, password } = req.body;
// 1) create salted+hashed version
const hashedPassword = bcrypt.hashSync(password, 10);
// 2) save user in database
await User.create({
email,
hashedPassword, // store only the hashed version
});
res.json({ message: "User registered!" });
});
// login route
app.post("/login", async (req, res) => {
const { email, password } = req.body;
// 1) find user by email
const user = await User.findOne({ where: { email } });
if (!user) {
return res.status(401).json({ message: "Invalid email or password" });
}
// 2) compare passwords
const isMatch = bcrypt.compareSync(password, user.hashedPassword);
if (!isMatch) {
return res.status(401).json({ message: "Invalid email or password" });
}
// 3) if match, user is authenticated
res.json({ message: "Logged in successfully!" });
});
In this simplified code:
bcrypt.compareSync.
That’s essentially all it takes to implement a secure password scheme with bcrypt.
Applications from social media giants to tiny hobby sites all rely on bcrypt or similar algorithms (like Argon2 or PBKDF2) for password storage. Historically, sites that skipped this step faced severe breaches. For instance, if you follow data breach news, you’ll see many catastrophic headlines about companies storing plaintext passwords or using outdated hashing methods. With bcrypt, you take advantage of a trusted cryptographic library that stands up well against brute-force and rainbow-table attacks.
Also, consider compliance requirements for handling user data. Whether it’s GDPR, HIPAA, or PCI-DSS, secure password storage is often part of the checklist. bcrypt helps ensure you meet those requirements.
hashSync (often “rounds”)
can be increased over time as hardware gets faster, making brute-forcing harder.bcrypt also has async methods
(bcrypt.hash, bcrypt.compare) to avoid blocking your event loop.argon2,
but bcrypt remains widely used and reputable.
You’ve seen how bcrypt fits right into your existing knowledge of salting and hashing:
bcrypt (or similarly vetted libraries)
to salt and hash passwords properly.hashSync to store passwords securely.
Only the salted+hashed version goes in the database.compareSync for authentication checks.
If it returns true, the user typed the correct password.Putting this all together, you now have a complete, best-practice approach for storing and verifying user passwords in Node. This is a major milestone in building secure applications—congratulations!