Authentication and SecurityLesson 5.3
Password hashing and secure login in Node.js
bcrypt vs scrypt, bcrypt salt rounds, password storage, login flow, timing-safe comparison, brute force protection, rate limiting
Never Store Plaintext Passwords
Use bcrypt for password hashing. It is battle-tested, includes a salt automatically, and has an adjustable cost factor.
npm install bcryptconst bcrypt = require('bcrypt');
const SALT_ROUNDS = 12;
async function hashPassword(plaintext) {
return bcrypt.hash(plaintext, SALT_ROUNDS);
}
async function verifyPassword(plaintext, storedHash) {
return bcrypt.compare(plaintext, storedHash);
}Secure Login Endpoint
app.post('/api/login', async (req, res) => {
const { email, password } = req.body;
const user = await User.findByEmail(email);
const dummyHash = '$2b$12$notavalidhashbutstillruns';
const hash = user ? user.passwordHash : dummyHash;
const valid = await bcrypt.compare(password, hash);
if (!user || !valid) {
return res.status(401).json({ error: 'Invalid credentials' });
}
const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET, { expiresIn: '15m' });
res.json({ token });
});