Files
biblical-guide.com/middleware.ts
andupetcu 196ca00194 Fix authentication state persistence and admin role display
- Implement complete authentication system with JWT token validation
- Add auth provider with persistent login state across page refreshes
- Create multilingual login/register forms with Material-UI components
- Fix token validation using raw SQL queries to bypass Prisma sync issues
- Add comprehensive error handling for expired/invalid tokens
- Create profile and settings pages with full i18n support
- Add proper user role management (admin/user) with database sync
- Implement secure middleware with CSRF protection and auth checks
- Add debug endpoints for troubleshooting authentication issues
- Fix Zustand store persistence for authentication state

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-21 01:06:30 +03:00

81 lines
2.8 KiB
TypeScript

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
// Avoid importing Node-only modules in Middleware (Edge runtime)
import createIntlMiddleware from 'next-intl/middleware'
// Internationalization configuration
const intlMiddleware = createIntlMiddleware({
locales: ['ro', 'en'],
defaultLocale: 'ro'
})
// Note: Avoid using Prisma or any Node-only APIs in Middleware.
// Middleware runs on the Edge runtime, where Prisma is not supported.
// If rate limiting is needed, implement it inside API route handlers
// (Node.js runtime) or via an external service (e.g., Upstash Redis).
export async function middleware(request: NextRequest) {
// Handle internationalization for non-API routes
if (!request.nextUrl.pathname.startsWith('/api')) {
return intlMiddleware(request)
}
// Skip API rate limiting here to stay Edge-safe
// Security headers for all responses
const response = NextResponse.next()
// Security headers
response.headers.set('X-Content-Type-Options', 'nosniff')
response.headers.set('X-Frame-Options', 'DENY')
response.headers.set('X-XSS-Protection', '1; mode=block')
response.headers.set('Referrer-Policy', 'origin-when-cross-origin')
response.headers.set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()')
// CSRF protection for state-changing operations
if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(request.method)) {
const origin = request.headers.get('origin')
const host = request.headers.get('host')
if (origin && host && !origin.endsWith(host)) {
return new NextResponse('Forbidden', { status: 403 })
}
}
// Authentication: perform only lightweight checks in Middleware (Edge).
// Defer full JWT verification to API route handlers (Node runtime).
const protectedPaths = ['/dashboard', '/profile', '/settings']
const isProtectedPath = protectedPaths.some(path =>
request.nextUrl.pathname.startsWith(path)
)
if (isProtectedPath) {
const token = request.cookies.get('authToken')?.value ||
request.headers.get('authorization')?.replace('Bearer ', '')
if (!token) {
// Extract locale from pathname for redirect
const locale = request.nextUrl.pathname.split('/')[1]
const isValidLocale = ['ro', 'en'].includes(locale)
const redirectLocale = isValidLocale ? locale : 'ro'
return NextResponse.redirect(new URL(`/${redirectLocale}/auth/login`, request.url))
}
}
return response
}
export const config = {
matcher: [
// Match all pathnames except for
// - api routes
// - _next (Next.js internals)
// - static files (images, etc.)
'/((?!api|_next|_vercel|.*\\..*).*)',
// However, match all pathnames within `/api`, except for the Middleware to run there
'/api/:path*',
'/dashboard/:path*'
],
}