Authentication with JWT in Node.js
Implement JWT authentication in Node.js. Learn token generation, verification, and protected routes.
Authentication with JWT in Node.js
JWT (JSON Web Token) is the standard for API authentication. No sessions, stateless, scalable.
How JWT Works
``` 1. User logs in with email/password 2. Server verifies, generates JWT 3. Server sends JWT to client 4. Client stores JWT (localStorage/cookie) 5. Client sends JWT with every request 6. Server verifies JWT, allows access ```
JWT Structure
``` header.payload.signature
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjF9.abc123signature ```
Setup
```bash npm install express jsonwebtoken bcryptjs ```
Generate Token
```javascript const jwt = require('jsonwebtoken');
const SECRET = process.env.JWT_SECRET || 'your-secret-key';
function generateToken(user) { return jwt.sign( { userId: user.id, email: user.email }, SECRET, { expiresIn: '7d' } ); } ```
Verify Token
```javascript function verifyToken(token) { try { return jwt.verify(token, SECRET); } catch (error) { return null; } } ```
Auth Middleware
```javascript function authMiddleware(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]; const decoded = verifyToken(token); if (!decoded) { return res.status(401).json({ error: 'Invalid token' }); } req.user = decoded; next(); } ```
Password Hashing
```javascript const bcrypt = require('bcryptjs');
// Hash password (registration) async function hashPassword(password) { return bcrypt.hash(password, 10); }
// Compare password (login) async function comparePassword(password, hash) { return bcrypt.compare(password, hash); } ```
Complete Auth Routes
```javascript const express = require('express'); const jwt = require('jsonwebtoken'); const bcrypt = require('bcryptjs');
const app = express(); app.use(express.json());
const SECRET = 'your-secret-key'; const users = []; // In-memory (use database in production)
// Register app.post('/api/register', async (req, res) => { const { email, password } = req.body; // Check if user exists if (users.find(u => u.email === email)) { return res.status(400).json({ error: 'Email already registered' }); } // Hash password const hashedPassword = await bcrypt.hash(password, 10); // Create user const user = { id: users.length + 1, email, password: hashedPassword }; users.push(user); // Generate token const token = jwt.sign({ userId: user.id }, SECRET, { expiresIn: '7d' }); res.status(201).json({ token, user: { id: user.id, email } }); });
// Login app.post('/api/login', async (req, res) => { const { email, password } = req.body; // Find user const user = users.find(u => u.email === email); if (!user) { return res.status(401).json({ error: 'Invalid credentials' }); } // Check password const valid = await bcrypt.compare(password, user.password); if (!valid) { return res.status(401).json({ error: 'Invalid credentials' }); } // Generate token const token = jwt.sign({ userId: user.id }, SECRET, { expiresIn: '7d' }); res.json({ token, user: { id: user.id, email: user.email } }); });
// Auth middleware function auth(req, res, next) { const authHeader = req.headers.authorization; if (!authHeader?.startsWith('Bearer ')) { return res.status(401).json({ error: 'Unauthorized' }); } try { const token = authHeader.split(' ')[1]; req.user = jwt.verify(token, SECRET); next(); } catch { res.status(401).json({ error: 'Invalid token' }); } }
// Protected route app.get('/api/profile', auth, (req, res) => { const user = users.find(u => u.id === req.user.userId); res.json({ id: user.id, email: user.email }); });
app.listen(3000); ```
Frontend Usage
```javascript // Login const response = await fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); const { token } = await response.json(); localStorage.setItem('token', token);
// Authenticated request const profile = await fetch('/api/profile', { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); ```
Key Takeaway
JWT enables stateless authentication. Hash passwords with bcrypt, generate tokens on login, verify tokens in middleware. Store tokens client-side, send in Authorization header. Simple and scalable!