mirror of
https://github.com/rmoren97/mc-manager.git
synced 2026-03-28 17:26:47 -07:00
67 lines
2.0 KiB
TypeScript
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).*)'],
|
|
}
|