📖 Notes
LESSON 27 OF 32
JWT Authentication
Who Is Making This Request?
Never store plain-text passwords. Hash them with bcrypt, then issue a signed JSON Web Token on login so the server can verify who's calling protected routes without a database lookup on every request.
Security Layer
Hashing, Signing, Verifying
🔐
bcrypt
One-way hashes a password so even the database owner can't read the original.
🎫
JWT
A signed token containing user data — issued at login, sent on every future request.
✍️
jwt.sign()
Creates a token signed with a secret key, usually with an expiry time.
🛡️
Protect Middleware
Verifies the token on incoming requests before letting them reach protected routes.
Register, Login, Protect
JSconst bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
// Register: hash before saving
const hashed = await bcrypt.hash(password, 10);
await User.create({ email, password: hashed });
// Login: compare + sign a token
const user = await User.findOne({ email });
const valid = await bcrypt.compare(password, user.password);
if (!valid) return res.status(401).json({ error: 'Invalid credentials' });
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: '7d' });
res.json({ token });
// Protect middleware
function protect(req, res, next) {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'No token' });
try {
req.user = jwt.verify(token, process.env.JWT_SECRET);
next();
} catch {
res.status(401).json({ error: 'Invalid token' });
}
}
app.get('/api/profile', protect, (req, res) => res.json(req.user));
⚠️
Never hardcode the secret
The JWT secret must come from an environment variable, never committed to Git — anyone with it can forge valid tokens for any user.