← back to Handbag Auth Nextjs
src/lib/securityHeaders.ts
64 lines
// Security Headers Middleware
// Protects against common web vulnerabilities
export function addSecurityHeaders(response: Response): void {
const headers = response.headers
// Prevent clickjacking attacks
headers.set('X-Frame-Options', 'DENY')
// Prevent MIME-type sniffing
headers.set('X-Content-Type-Options', 'nosniff')
// Enable XSS protection in older browsers
headers.set('X-XSS-Protection', '1; mode=block')
// Referrer policy - only send origin on cross-origin requests
headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
// Permissions policy - disable unnecessary features
headers.set('Permissions-Policy', 'geolocation=(), microphone=(), camera=()')
// Content Security Policy - prevent XSS and injection attacks
const csp = [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval'", // Next.js requires unsafe-inline/eval
"style-src 'self' 'unsafe-inline'", // Tailwind requires unsafe-inline
"img-src 'self' data: https: http:", // Allow external images (Yahoo Japan, etc.)
"font-src 'self' data:",
"connect-src 'self'",
"frame-ancestors 'none'",
"base-uri 'self'",
"form-action 'self'"
].join('; ')
headers.set('Content-Security-Policy', csp)
// Strict Transport Security - force HTTPS (only in production)
if (process.env.NODE_ENV === 'production') {
headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains')
}
}
/**
* CORS headers for API endpoints
*/
export function addCorsHeaders(response: Response, origin?: string): void {
const headers = response.headers
// In production, restrict to specific origins
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') || ['*']
if (origin && allowedOrigins.includes('*')) {
headers.set('Access-Control-Allow-Origin', origin)
} else if (origin && allowedOrigins.includes(origin)) {
headers.set('Access-Control-Allow-Origin', origin)
} else {
headers.set('Access-Control-Allow-Origin', allowedOrigins[0])
}
headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization')
headers.set('Access-Control-Max-Age', '86400') // 24 hours
}