mc-manager/src/middleware.ts
2026-02-07 12:20:12 -08:00

67 lines
2.0 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
const publicRoutes = ['/login', '/api/auth/login', '/api/auth/verify-2fa', '/api/health']
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl
// Allow public routes
if (publicRoutes.some(route => pathname.startsWith(route))) {
return addSecurityHeaders(NextResponse.next())
}
// Allow static assets
if (
pathname.startsWith('/_next') ||
pathname.startsWith('/favicon') ||
pathname.includes('.')
) {
return NextResponse.next()
}
// Check for session token
const sessionToken = request.cookies.get('session-token')?.value
if (!sessionToken) {
// API routes return 401
if (pathname.startsWith('/api/')) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
// Pages redirect to login
const loginUrl = new URL('/login', request.url)
loginUrl.searchParams.set('redirect', pathname)
return NextResponse.redirect(loginUrl)
}
// CORS enforcement in production
if (process.env.NODE_ENV === 'production' && pathname.startsWith('/api/')) {
const origin = request.headers.get('origin')
const allowedOrigins = [
process.env.NEXT_PUBLIC_APP_URL,
].filter(Boolean)
if (origin && !allowedOrigins.includes(origin)) {
return NextResponse.json({ error: 'CORS: Origin not allowed' }, { status: 403 })
}
}
return addSecurityHeaders(NextResponse.next())
}
function addSecurityHeaders(response: NextResponse): NextResponse {
response.headers.set('X-Frame-Options', 'DENY')
response.headers.set('X-Content-Type-Options', 'nosniff')
response.headers.set('X-XSS-Protection', '1; mode=block')
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
response.headers.set(
'Permissions-Policy',
'geolocation=(), microphone=(), camera=()'
)
return response
}
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
}