2025-12-03 21:26:14 +01:00

67 lines
1.7 KiB
JavaScript

import rateLimit from 'express-rate-limit';
import helmet from 'helmet';
import csrf from 'csurf';
import config from '../config.js';
// Rate limiter for general API requests
export const apiLimiter = rateLimit({
windowMs: config.rateLimit.windowMs,
max: config.rateLimit.maxRequests,
message: 'Too many requests, please try again later',
standardHeaders: true,
legacyHeaders: false,
});
// Stricter rate limiter for auth endpoints
export const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5,
message: 'Too many login attempts, please try again later',
skipSuccessfulRequests: true,
});
// Security headers middleware
export function securityHeaders(req, res, next) {
helmet()(req, res, next);
}
// CSRF protection
export const csrfProtection = csrf({ cookie: false });
// Request logging
export function requestLogger(req, res, next) {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
console.log(
`[${new Date().toISOString()}] ${req.method} ${req.path} - ${res.statusCode} - ${duration}ms`
);
});
next();
}
// Error handler middleware
export function errorHandler(err, req, res, next) {
console.error('Error:', err);
if (err.code === 'EBADCSRFTOKEN') {
return res.status(403).json({ error: 'Invalid CSRF token' });
}
if (err.message && err.message.includes('OIDC')) {
return res.status(401).json({ error: 'Authentication failed' });
}
res.status(err.status || 500).json({
error: err.message || 'Internal server error',
});
}
// Middleware to attach CSRF token to response
export function attachCsrfToken(req, res, next) {
res.locals.csrfToken = req.csrfToken();
next();
}