feat: implement security enhancements (task 17)

- Add rate limiting for login, registration, and invitations
- Implement CSRF protection with SameSite cookies and security headers
- Configure secure session cookies with httpOnly and secure flags
- Enhance input sanitization for XSS and injection prevention
- Add comprehensive security tests (41 tests passing)
- Document security enhancements in SECURITY_ENHANCEMENTS.md

Requirements: 9.3, 9.4, 9.5
This commit is contained in:
2025-12-02 01:29:35 +00:00
parent 2ce89e7c6c
commit 534796edd7
9 changed files with 984 additions and 16 deletions

View File

@@ -3,13 +3,16 @@ import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
/**
* Middleware for session validation and route protection
* Middleware for session validation, route protection, and security headers
*
* This middleware:
* - Validates session tokens on protected routes
* - Redirects unauthenticated users to login
* - Handles session expiration
* - Allows access to auth pages for unauthenticated users
* - Adds security headers (CSRF protection, XSS protection, etc.)
*
* Requirements: 3.3, 3.5, 9.4 (CSRF protection), 9.5 (security headers)
*/
export default auth((req) => {
const { nextUrl } = req
@@ -25,25 +28,63 @@ export default auth((req) => {
// Define auth pages (login, register, etc.)
const isAuthPage = nextUrl.pathname.startsWith("/auth")
// Create response
let response: NextResponse
// Allow access to auth pages regardless of authentication status
if (isAuthPage) {
// If already logged in and trying to access login/register, redirect to home
if (isLoggedIn && (nextUrl.pathname === "/auth/login" || nextUrl.pathname === "/auth/register")) {
return NextResponse.redirect(new URL("/", req.url))
response = NextResponse.redirect(new URL("/", req.url))
} else {
response = NextResponse.next()
}
return NextResponse.next()
}
// Redirect to login if accessing protected route without authentication
if (isProtectedRoute && !isLoggedIn) {
else if (isProtectedRoute && !isLoggedIn) {
const loginUrl = new URL("/auth/login", req.url)
// Add callback URL to redirect back after login
loginUrl.searchParams.set("callbackUrl", nextUrl.pathname)
return NextResponse.redirect(loginUrl)
response = NextResponse.redirect(loginUrl)
}
// Allow access to public routes
else {
response = NextResponse.next()
}
// Allow access to public routes
return NextResponse.next()
// Add security headers - Requirement 9.4, 9.5
const headers = response.headers
// CSRF Protection - SameSite cookie attribute is set in auth.ts
// This header provides additional CSRF protection
headers.set('X-Content-Type-Options', 'nosniff')
// XSS Protection
headers.set('X-XSS-Protection', '1; mode=block')
// Prevent clickjacking attacks
headers.set('X-Frame-Options', 'DENY')
// Referrer Policy - don't leak referrer information
headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
// Content Security Policy - helps prevent XSS attacks
// Note: This is a basic CSP. You may need to adjust based on your needs
const csp = [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval'", // unsafe-inline and unsafe-eval needed for Next.js
"style-src 'self' 'unsafe-inline'", // unsafe-inline needed for Tailwind
"img-src 'self' data: blob:",
"font-src 'self' data:",
"connect-src 'self'",
"frame-ancestors 'none'",
].join('; ')
headers.set('Content-Security-Policy', csp)
// Permissions Policy - restrict access to browser features
headers.set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()')
return response
})
/**