Authentication & JWT
JSON Web Tokens (JWT) are a compact, self-contained way to securely transmit authentication data between client and server. Combined with bcrypt for password hashing, they form the foundation of modern stateless authentication.
1 Registration & Login Flow
JavaScript — Auth Controller
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('../models/User');
// REGISTER
async function register(req, res) {
const { name, email, password } = req.body;
// Check if user exists
const existing = await User.findOne({ email });
if (existing) return res.status(409).json({ error: 'Email already registered' });
// Hash password (cost factor 12)
const passwordHash = await bcrypt.hash(password, 12);
const user = await User.create({ name, email, passwordHash });
res.status(201).json({ id: user._id, name, email });
}
// LOGIN
async function login(req, res) {
const { email, password } = req.body;
const user = await User.findOne({ email }).select('+passwordHash');
if (!user) return res.status(401).json({ error: 'Invalid credentials' });
const valid = await bcrypt.compare(password, user.passwordHash);
if (!valid) return res.status(401).json({ error: 'Invalid credentials' });
// Sign JWT — expires in 7 days
const token = jwt.sign(
{ userId: user._id, role: user.role },
process.env.JWT_SECRET,
{ expiresIn: '7d' }
);
res.json({ token, user: { id: user._id, name: user.name, email } });
}
module.exports = { register, login };
2 JWT Auth Middleware
JavaScript — Protect Routes
const jwt = require('jsonwebtoken');
function authenticate(req, res, next) {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'No token provided' });
}
const token = authHeader.split(' ')[1];
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded; // attach payload to request
next();
} catch (err) {
res.status(401).json({ error: 'Invalid or expired token' });
}
}
// Role-based authorization
function authorize(...roles) {
return (req, res, next) => {
if (!roles.includes(req.user.role)) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
next();
};
}
// Usage
app.get('/admin', authenticate, authorize('admin'), (req, res) => {
res.json({ message: 'Admin panel' });
});
3 Code Challenge
Challenge: Add a
POST /auth/refresh endpoint that accepts a refresh token (stored in an httpOnly cookie) and returns a new short-lived access token.