/**
* API Rate Limiting & Auth Middleware
* Production security patterns
*/
import { Request, Response, NextFunction } from "express";
import rateLimit from "express-rate-limit";
import helmet from "helmet";
// Rate limiting configuration
export const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
limit: 100, // 100 requests per window
standardHeaders: true,
legacyHeaders: false,
message: { error: "Too many requests, please try again later" },
skip: (req) => {
// Skip admin users
return req.headers["x-admin-key"] === process.env.ADMIN_KEY;
},
});
// Strict rate limit for auth endpoints
export const authLimiter = rateLimit({
windowMs: 60 * 60 * 1000, // 1 hour
limit: 5, // 5 attempts per hour
message: { error: "Too many login attempts, try again later" },
});
// API Key authentication middleware
export function apiKeyAuth(req: Request, res: Response, next: NextFunction) {
const apiKey = req.headers["x-api-key"] as string;
if (!apiKey) {
return res.status(401).json({ error: "Missing API key" });
}
// Validate API key (implement your logic)
const isValid = validateApiKey(apiKey);
if (!isValid) {
return res.status(401).json({ error: "Invalid API key" });
}
next();
}
// JWT authentication middleware
export function jwtAuth(req: Request, res: Response, next: NextFunction) {
const authHeader = req.headers.authorization;
if (!authHeader?.startsWith("Bearer ")) {
return res.status(401).json({ error: "Missing authorization token" });
}
const token = authHeader.split(" ")[1];
try {
// Verify JWT (implement your logic)
const decoded = verifyJWT(token);
(req as any).user = decoded;
next();
} catch (err) {
return res.status(401).json({ error: "Invalid token" });
}
}
// Helper functions (implement these)
function validateApiKey(key: string): boolean {
// TODO: Check against database
return key.startsWith("sk-");
}
function verifyJWT(token: string): any {
// TODO: Use jsonwebtoken library
return { userId: "123" };
}
// Security headers
export const securityMiddleware = helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
},
},
crossOriginEmbedderPolicy: true,
crossOriginOpenerPolicy: true,
crossOriginResourcePolicy: { policy: "same-origin" },
dnsPrefetchControl: true,
frameguard: { action: "deny" },
hidePoweredBy: true,
hsts: true,
ieNoOpen: true,
noSniff: true,
originAgentCluster: true,
permittedCrossDomainPolicies: true,
referrerPolicy: { policy: "strict-origin-when-cross-origin" },
xssFilter: true,
});