API Security
Protect your API against common attacks.
Helmet
bash
npm install helmettypescript
import helmet from 'helmet'; app.use(helmet());CORS Configuration
typescript
import cors from 'cors'; app.use(cors({ origin: ['http://localhost:3000', 'https://myapp.com'], methods: ['GET', 'POST', 'PUT', 'DELETE'], credentials: true,}));Rate Limiting
typescript
import rateLimit from 'express-rate-limit'; export const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, message: { error: 'Too many requests' },}); // Stricter for auth routesexport const authLimiter = rateLimit({ windowMs: 60 * 60 * 1000, // 1 hour max: 5, skipSuccessfulRequests: true,}); app.use('/api', limiter);app.use('/api/auth/login', authLimiter);Input Sanitization
bash
npm install express-mongo-sanitize xss-cleantypescript
import mongoSanitize from 'express-mongo-sanitize';import xss from 'xss-clean'; app.use(mongoSanitize());app.use(xss());Brute Force Protection
typescript
const MAX_ATTEMPTS = 5;const BLOCK_DURATION = 15 * 60; // 15 minutes async login(email: string, password: string) { const blockKey = `login_blocked:${email}`; const attemptsKey = `login_attempts:${email}`; const isBlocked = await redis.get(blockKey); if (isBlocked) { throw new AppError('Account temporarily blocked', 429); } const user = await prisma.user.findUnique({ where: { email } }); const isValid = user && await bcrypt.compare(password, user.password); if (!isValid) { const attempts = await redis.incr(attemptsKey); await redis.expire(attemptsKey, BLOCK_DURATION); if (attempts >= MAX_ATTEMPTS) { await redis.setex(blockKey, BLOCK_DURATION, '1'); throw new AppError('Account blocked for 15 minutes', 429); } throw new AppError('Invalid credentials', 401); } await redis.del(attemptsKey); return this.generateToken(user);}Summary
- ✅ Helmet security headers
- ✅ CORS configuration
- ✅ Rate limiting
- ✅ Input sanitization
- ✅ Brute force protection
Next lesson: Docker and Containers! 🚀