Why Authentication Matters
APIs need authentication to protect sensitive data and prevent unauthorized access. JWT (JSON Web Tokens) is a popular authentication method.
Setting Up JWT Authentication
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const mongoose = require('mongoose');
const app = express();
app.use(express.json());
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
// User Schema
const userSchema = new mongoose.Schema({
email: String,
password: String
});
const User = mongoose.model('User', userSchema);
// Register endpoint
app.post('/api/register', async (req, res) => {
try {
const { email, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 10);
const user = new User({ email, password: hashedPassword });
await user.save();
res.status(201).json({ message: 'User created' });
} catch (error) {
res.status(400).json({ error: error.message });
}
});
// Login endpoint
app.post('/api/login', async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
const validPassword = await bcrypt.compare(password, user.password);
if (!validPassword) {
return res.status(401).json({ error: 'Invalid credentials' });
}
const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '24h' });
res.json({ token });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Middleware to verify token
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'Access token required' });
}
jwt.verify(token, JWT_SECRET, (err, user) => {
if (err) {
return res.status(403).json({ error: 'Invalid token' });
}
req.user = user;
next();
});
}
// Protected route
app.get('/api/profile', authenticateToken, async (req, res) => {
const user = await User.findById(req.user.userId);
res.json({ email: user.email });
});
app.listen(3000, () => console.log('Server running'));
Using the Authenticated API
// Frontend: Login and store token
async function login(email, password) {
const response = await fetch('http://localhost:3000/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
});
const data = await response.json();
localStorage.setItem('token', data.token);
}
// Make authenticated request
async function getProfile() {
const token = localStorage.getItem('token');
const response = await fetch('http://localhost:3000/api/profile', {
headers: {
'Authorization': `Bearer ${token}`
}
});
const data = await response.json();
return data;
}
Security Best Practices
- Use HTTPS in production
- Store JWT secrets securely
- Implement token expiration
- Use refresh tokens for long sessions
- Validate and sanitize all inputs