Files
asle/backend/src/middleware/security.ts
defiQUG 507d9a35b1 Add initial project structure and documentation files
- Created .gitignore to exclude sensitive files and directories.
- Added API documentation in API_DOCUMENTATION.md.
- Included deployment instructions in DEPLOYMENT.md.
- Established project structure documentation in PROJECT_STRUCTURE.md.
- Updated README.md with project status and team information.
- Added recommendations and status tracking documents.
- Introduced testing guidelines in TESTING.md.
- Set up CI workflow in .github/workflows/ci.yml.
- Created Dockerfile for backend and frontend setups.
- Added various service and utility files for backend functionality.
- Implemented frontend components and pages for user interface.
- Included mobile app structure and services.
- Established scripts for deployment across multiple chains.
2025-12-03 21:22:31 -08:00

120 lines
3.0 KiB
TypeScript

import { Request, Response, NextFunction } from 'express';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
/**
* Security middleware configurations
*/
// Rate limiting configurations
export const createRateLimiter = (windowMs: number, max: number) => {
return rateLimit({
windowMs,
max,
message: 'Too many requests from this IP, please try again later.',
standardHeaders: true,
legacyHeaders: false,
});
};
// Specific rate limiters
export const authRateLimiter = createRateLimiter(15 * 60 * 1000, 5); // 5 requests per 15 minutes
export const apiRateLimiter = createRateLimiter(60 * 1000, 100); // 100 requests per minute
export const strictRateLimiter = createRateLimiter(60 * 1000, 10); // 10 requests per minute
/**
* Enhanced security headers
*/
export const securityHeaders = helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", 'data:', 'https:'],
connectSrc: ["'self'"],
fontSrc: ["'self'"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'none'"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true,
},
frameguard: {
action: 'deny',
},
noSniff: true,
xssFilter: true,
});
/**
* CORS configuration based on environment
*/
export const corsConfig = {
origin: (origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) => {
const allowedOrigins = process.env.CORS_ORIGINS?.split(',') || [process.env.CORS_ORIGIN || '*'];
if (process.env.NODE_ENV === 'production') {
if (!origin || allowedOrigins.includes(origin) || allowedOrigins.includes('*')) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
} else {
callback(null, true);
}
},
credentials: true,
optionsSuccessStatus: 200,
};
/**
* Input validation middleware
*/
export const validateInput = (schema: any) => {
return (req: Request, res: Response, next: NextFunction) => {
try {
schema.parse(req.body);
next();
} catch (error: any) {
res.status(400).json({
error: 'Validation error',
details: error.errors,
});
}
};
};
/**
* Sanitize input to prevent XSS
*/
export const sanitizeInput = (req: Request, res: Response, next: NextFunction) => {
if (req.body && typeof req.body === 'object') {
const sanitize = (obj: any): any => {
if (typeof obj === 'string') {
// Remove potentially dangerous characters
return obj.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
}
if (Array.isArray(obj)) {
return obj.map(sanitize);
}
if (obj && typeof obj === 'object') {
const sanitized: any = {};
for (const key in obj) {
sanitized[key] = sanitize(obj[key]);
}
return sanitized;
}
return obj;
};
req.body = sanitize(req.body);
}
next();
};