Topic 53 of 55
Bcrypt Password Hashing
Overview
Storing plain-text passwords in a database is a massive security failure. You must hash passwords before saving them. Bcrypt is an industry-standard library that hashes passwords and automatically adds 'salt' (random data) to prevent rainbow table attacks.
Syntax
javascript
// 1. Install bcrypt
// npm install bcrypt
const bcrypt = require('bcrypt');
const saltRounds = 10; // The higher the number, the slower (more secure) it is
// Hashing a password (e.g., during Registration)
async function registerUser(plainTextPassword) {
// Generate salt and hash together
const hashedPassword = await bcrypt.hash(plainTextPassword, saltRounds);
console.log(hashedPassword); // e.g., $2b$10$w... (60 chars long)
// Save hashedPassword to DB
}
// Verifying a password (e.g., during Login)
async function loginUser(plainTextPassword, hashFromDatabase) {
// bcrypt compares the plain text to the hash securely
const isMatch = await bcrypt.compare(plainTextPassword, hashFromDatabase);
if (isMatch) console.log("Login successful!");
else console.log("Incorrect password!");
}Common Pitfalls
- Bcrypt hashing is intentionally slow and CPU-intensive to thwart brute-force attacks. Doing it synchronously (`bcrypt.hashSync`) will block the Node.js event loop. Always use the async versions.
- If you use a pre-save hook in Mongoose, remember that operations like `findByIdAndUpdate` do NOT trigger `pre('save')` hooks. You must use `.save()` to trigger them.
Real-World Example
Integrating bcrypt directly into a Mongoose Schema (Pre-save Hook):
example
javascript
const userSchema = new mongoose.Schema({
email: String,
password: { type: String, required: true }
});
// Run this function BEFORE saving the document to the DB
userSchema.pre('save', async function(next) {
// Only hash the password if it has been modified (or is new)
if (!this.isModified('password')) return next();
try {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
} catch (err) {
next(err);
}
});
// Usage:
// const user = new User({ email: 'x', password: 'myPassword123' });
// await user.save(); // The DB will only contain the hashed version!