Initial commit
This commit is contained in:
143
templates/nextjs/middleware.ts
Normal file
143
templates/nextjs/middleware.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* Next.js Middleware with Clerk Authentication
|
||||
*
|
||||
* This middleware protects routes using Clerk's clerkMiddleware.
|
||||
* Place this file in the root of your Next.js project.
|
||||
*
|
||||
* Dependencies:
|
||||
* - @clerk/nextjs@^6.33.3
|
||||
*
|
||||
* CRITICAL (v6 Breaking Change):
|
||||
* - auth.protect() is now async - must use await
|
||||
* - Source: https://clerk.com/changelog/2024-10-22-clerk-nextjs-v6
|
||||
*/
|
||||
|
||||
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
|
||||
|
||||
/**
|
||||
* Define public routes (routes that don't require authentication)
|
||||
*
|
||||
* Glob patterns supported:
|
||||
* - '/path' - exact match
|
||||
* - '/path(.*)' - path and all sub-paths
|
||||
* - '/api/public/*' - wildcard
|
||||
*/
|
||||
const isPublicRoute = createRouteMatcher([
|
||||
'/', // Homepage
|
||||
'/sign-in(.*)', // Sign-in page and sub-paths
|
||||
'/sign-up(.*)', // Sign-up page and sub-paths
|
||||
'/api/public(.*)', // Public API routes
|
||||
'/api/webhooks(.*)', // Webhook endpoints
|
||||
'/about', // Static pages
|
||||
'/pricing',
|
||||
'/contact',
|
||||
])
|
||||
|
||||
/**
|
||||
* Alternative: Define protected routes instead
|
||||
*
|
||||
* Uncomment this pattern if you prefer to explicitly protect
|
||||
* specific routes rather than inverting the logic:
|
||||
*/
|
||||
/*
|
||||
const isProtectedRoute = createRouteMatcher([
|
||||
'/dashboard(.*)',
|
||||
'/profile(.*)',
|
||||
'/admin(.*)',
|
||||
'/api/private(.*)',
|
||||
])
|
||||
|
||||
export default clerkMiddleware(async (auth, request) => {
|
||||
if (isProtectedRoute(request)) {
|
||||
await auth.protect()
|
||||
}
|
||||
})
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default Pattern: Protect all routes except public ones
|
||||
*
|
||||
* CRITICAL:
|
||||
* - auth.protect() MUST be awaited (async in v6)
|
||||
* - Without await, route protection will not work
|
||||
*/
|
||||
export default clerkMiddleware(async (auth, request) => {
|
||||
if (!isPublicRoute(request)) {
|
||||
await auth.protect()
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Matcher Configuration
|
||||
*
|
||||
* Defines which paths run middleware.
|
||||
* This is the recommended configuration from Clerk.
|
||||
*/
|
||||
export const config = {
|
||||
matcher: [
|
||||
// Skip Next.js internals and static files
|
||||
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
|
||||
|
||||
// Always run for API routes
|
||||
'/(api|trpc)(.*)',
|
||||
],
|
||||
}
|
||||
|
||||
/**
|
||||
* Advanced: Role-Based Protection
|
||||
*
|
||||
* Protect routes based on user role or organization membership:
|
||||
*/
|
||||
/*
|
||||
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
|
||||
|
||||
const isAdminRoute = createRouteMatcher(['/admin(.*)'])
|
||||
const isOrgRoute = createRouteMatcher(['/org(.*)'])
|
||||
|
||||
export default clerkMiddleware(async (auth, request) => {
|
||||
// Admin routes require 'admin' role
|
||||
if (isAdminRoute(request)) {
|
||||
await auth.protect((has) => {
|
||||
return has({ role: 'admin' })
|
||||
})
|
||||
}
|
||||
|
||||
// Organization routes require organization membership
|
||||
if (isOrgRoute(request)) {
|
||||
await auth.protect((has) => {
|
||||
return has({ permission: 'org:member' })
|
||||
})
|
||||
}
|
||||
|
||||
// All other routes use default protection
|
||||
if (!isPublicRoute(request)) {
|
||||
await auth.protect()
|
||||
}
|
||||
})
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
|
||||
'/(api|trpc)(.*)',
|
||||
],
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Troubleshooting:
|
||||
*
|
||||
* 1. Routes not protected?
|
||||
* - Ensure auth.protect() is awaited
|
||||
* - Check matcher configuration includes your routes
|
||||
* - Verify middleware.ts is in project root
|
||||
*
|
||||
* 2. Infinite redirects?
|
||||
* - Ensure sign-in/sign-up routes are in isPublicRoute
|
||||
* - Check NEXT_PUBLIC_CLERK_SIGN_IN_URL in .env.local
|
||||
*
|
||||
* 3. API routes returning HTML?
|
||||
* - Verify '/(api|trpc)(.*)' is in matcher
|
||||
* - Check API routes are not in isPublicRoute if protected
|
||||
*
|
||||
* Official Docs: https://clerk.com/docs/reference/nextjs/clerk-middleware
|
||||
*/
|
||||
Reference in New Issue
Block a user