Password hashing with bcrypt helps keep user passwords safe by turning them into secret codes that are hard to guess or steal.
Password hashing with bcrypt in Express
Start learning this pattern below
Jump into concepts and practice - no test required
or
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
Syntax
Express
import bcrypt from 'bcrypt'; // To hash a password const hashedPassword = await bcrypt.hash(password, saltRounds); // To check a password const isMatch = await bcrypt.compare(password, hashedPassword);
saltRounds controls how strong the hashing is. Higher means safer but slower.
Always use await or handle promises because bcrypt works asynchronously.
Examples
Express
const bcrypt = require('bcrypt'); const saltRounds = 10; const password = 'mySecret123'; bcrypt.hash(password, saltRounds).then(hash => { console.log(hash); });
Express
const bcrypt = require('bcrypt'); const password = 'mySecret123'; const hashedPassword = '$2b$10$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36Z1f8q1Q1v6q9v7v5Y5F6e'; bcrypt.compare(password, hashedPassword).then(result => { console.log(result); // true or false });
Sample Program
This Express app lets users register with a hashed password and login by checking the hashed password. It keeps users in memory for simplicity.
Express
import express from 'express'; import bcrypt from 'bcrypt'; const app = express(); app.use(express.json()); const users = []; const saltRounds = 10; // Register route to hash password and save user app.post('/register', async (req, res) => { const { username, password } = req.body; if (!username || !password) { return res.status(400).send('Username and password required'); } const hashedPassword = await bcrypt.hash(password, saltRounds); users.push({ username, password: hashedPassword }); res.send('User registered'); }); // Login route to check password app.post('/login', async (req, res) => { const { username, password } = req.body; const user = users.find(u => u.username === username); if (!user) { return res.status(400).send('User not found'); } const match = await bcrypt.compare(password, user.password); if (match) { res.send('Login successful'); } else { res.status(401).send('Wrong password'); } }); app.listen(3000, () => { console.log('Server running on http://localhost:3000'); });
Important Notes
Never store plain passwords. Always hash before saving.
Use a reasonable saltRounds value (10-12) to balance security and speed.
bcrypt automatically adds a unique salt to each password hash.
Summary
Password hashing keeps user passwords safe by turning them into secret codes.
Use bcrypt's hash to create a hashed password and compare to check it.
Always handle bcrypt asynchronously with await or promises.
Practice
1. What is the main purpose of using
bcrypt in an Express app?easy
Solution
Step 1: Understand bcrypt's role
Bcrypt is a library designed to hash passwords securely, making them hard to read if stolen.Step 2: Identify the correct purpose in Express
In Express apps, bcrypt is used to hash passwords before storing them in a database to protect user data.Final Answer:
To securely hash user passwords before saving them -> Option AQuick Check:
Password hashing = Secure storage [OK]
Hint: Bcrypt is for password security, not speed or formatting [OK]
Common Mistakes:
- Thinking bcrypt speeds up server
- Confusing bcrypt with session management
- Using bcrypt for data formatting
2. Which of the following is the correct way to hash a password asynchronously using bcrypt in Express?
easy
Solution
Step 1: Identify asynchronous bcrypt hashing syntax
Bcrypt's async hash function requiresawaitand two arguments: the password and salt rounds.Step 2: Check each option
const hashed = await bcrypt.hash(password, 10); usesawait bcrypt.hash(password, 10);which is correct async usage. const hashed = bcrypt.hashSync(password, 10); is synchronous, C is wrong function, B misses salt rounds.Final Answer:
const hashed = await bcrypt.hash(password, 10); -> Option CQuick Check:
Async hash needs await and salt rounds [OK]
Hint: Async bcrypt hash always uses await and salt rounds [OK]
Common Mistakes:
- Using synchronous hashSync instead of async
- Calling compare instead of hash
- Omitting salt rounds argument
3. What will be the output of this code snippet?
const bcrypt = require('bcrypt');
async function test() {
const password = 'secret123';
const hash = await bcrypt.hash(password, 5);
const match = await bcrypt.compare('secret123', hash);
console.log(match);
}
test();medium
Solution
Step 1: Understand bcrypt.hash and bcrypt.compare
The code hashes 'secret123' with salt rounds 5, then compares the original password to the hash.Step 2: Analyze the compare result
Since the password matches the hash,bcrypt.comparereturns true, which is logged.Final Answer:
true -> Option DQuick Check:
Password matches hash = true [OK]
Hint: Compare returns true if password matches hash [OK]
Common Mistakes:
- Expecting false because of low salt rounds
- Thinking compare returns the hash
- Missing await causing undefined
4. Identify the error in this Express route using bcrypt:
app.post('/signup', async (req, res) => {
const { password } = req.body;
const hashed = bcrypt.hash(password, 10);
// Save hashed password to DB
res.send('User created');
});medium
Solution
Step 1: Check bcrypt.hash usage
Bcrypt.hash is async and returns a Promise, so it needsawaitto get the hashed string.Step 2: Identify missing await effect
Withoutawait,hashedis a Promise, not the actual hash, causing errors when saving.Final Answer:
Missing await before bcrypt.hash causing a Promise instead of hash -> Option BQuick Check:
Async bcrypt.hash needs await [OK]
Hint: Always await async bcrypt.hash to get the hash string [OK]
Common Mistakes:
- Forgetting await on async bcrypt.hash
- Using wrong number of arguments
- Thinking hashSync is mandatory
5. You want to create a secure signup route in Express that hashes the password and then verifies it immediately to confirm hashing worked. Which code snippet correctly does this?
hard
Solution
Step 1: Check async usage and salt rounds
app.post('/signup', async (req, res) => { const { password } = req.body; const hash = await bcrypt.hash(password, 12); const valid = await bcrypt.compare(password, hash); if (valid) res.send('Signup successful'); else res.status(500).send('Hashing error'); }); uses async/await correctly and provides salt rounds (12) to bcrypt.hash, which is best practice.Step 2: Verify immediate password check
It compares the original password with the hash using await bcrypt.compare, then sends success if valid.Step 3: Analyze other options
app.post('/signup', (req, res) => { const { password } = req.body; const hash = bcrypt.hashSync(password, 12); const valid = bcrypt.compareSync(password, hash); if (valid) res.send('Signup successful'); else res.status(500).send('Hashing error'); }); uses sync methods which block the server, C misses await causing Promises, D misses salt rounds in hash.Final Answer:
Option A code snippet with async/await and salt rounds -> Option AQuick Check:
Async hash with salt rounds + compare = correct [OK]
Hint: Use async/await with salt rounds and compare for secure signup [OK]
Common Mistakes:
- Using synchronous bcrypt methods in async routes
- Forgetting await causing Promises
- Omitting salt rounds in hash
