Authentication and AuthorizationLesson 4.5
Securing passwords — bcrypt hashing and common mistakes
bcrypt algorithm, salt rounds, genSalt, hash, compare, timing attacks, never store plaintext, never log passwords, rate limiting login
Secure Password Storage with bcrypt
Passwords must never be stored in plaintext or using fast hash functions like MD5 or SHA-256. bcrypt is slow by design — it makes brute-force attacks computationally expensive.
Hashing on Registration
const bcrypt = require('bcrypt');
// Registration
const registerUser = async (req, res, next) => {
try {
const { email, password } = req.body;
// Cost factor 12 = ~300ms on modern hardware. Adjust to keep under 1s.
const passwordHash = await bcrypt.hash(password, 12);
const user = await User.create({ email, passwordHash });
res.status(201).json({ id: user.id, email: user.email });
} catch (err) { next(err); }
};Verifying on Login
const match = await bcrypt.compare(candidatePassword, storedHash);
// bcrypt.compare is constant-time — safe against timing attacks
// Returns true/false, never throws on mismatchCommon Mistakes
Never log req.body wholesale — it may contain passwords. Never return the passwordHash field in API responses. Never compare passwords with === — use bcrypt.compare which is constant-time. Rate-limit /auth/login to slow credential stuffing: install express-rate-limit and allow maximum 5 attempts per IP per 15 minutes.
const rateLimit = require('express-rate-limit');
app.use('/auth/login', rateLimit({ windowMs: 15*60*1000, max: 5 }));