I'm trying to make NextJS middleware mark dynamic routea under /dashboard/[user]
as protected thereby performing auth checks when navigating to and from such route. However, I have been unable to do that using the convention /dashboard/:path*
or /dashboard/(path)
Here is my middleware.ts
import { auth } from "@/auth"
import { NextRequest, NextResponse } from 'next/server'
// 1. Specify protected and public routes
const protectedRoutes = ['/dashboard/:param*', '/message/:path*']
const publicRoutes = ['/login', '/signup', '/']
export default async function middleware(req: NextRequest) {
// 2. Check if the current route is protected or public
const path = req.nextUrl.pathname
const isProtectedRoute = protectedRoutes.includes(path)
const isPublicRoute = publicRoutes.includes(path)
// 3. Decrypt the session from the cookie
const session = await auth();
console.log('Middleware: Is route protected? ', isProtectedRoute, req.nextUrl.pathname)
// 5. Redirect to /login if the user is not authenticated
if (isProtectedRoute && session == null) {
console.log('Should redirect')
return NextResponse.redirect(new URL('/login', req.nextUrl))
}
// 6. Redirect to /dashboard if the user is authenticated
if (
isPublicRoute &&
session?.user &&
!req.nextUrl.pathname.startsWith('/')
) {
return NextResponse.redirect(new URL('/dashboard', req.nextUrl))
}
return NextResponse.next()
}
// Routes Middleware should not run on
export const config = {
matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
}
The middleware doesn't match dynamic routes
On navigating to user's dashboard at /dashboard/sam32
, the middleware doesn't mark it has protected hence fails to performs auth check. Although if I hard-code the user id in the protected routes array, auth checks are performed appropriately. Why does the middleware fail to mark those dynamic routes or is there a different approach to dynamic url identification in NextJS?
As @Dave Lin commented, I was comparing a regex pattern to a string which is why it won't work. I had to modify my code to the following:
import { auth } from "@/auth"
import { NextRequest, NextResponse } from 'next/server'
// 1. Specify protected and public routes
// const protectedRoutes = ['/message/:path*'] commented out
const publicRoutes = ['/login', '/signup', '/']
export default async function middleware(req: NextRequest) {
// 2. Check if the current route is protected or public
const path = req.nextUrl.pathname
const isProtectedRoute = path.startsWith('/dashboard/')
const isPublicRoute = publicRoutes.includes(path)
// 3. Decrypt the session from the cookie
const session = await auth();
// 5. Redirect to /login if the user is not authenticated
if (isProtectedRoute && session?.user == null) {
return NextResponse.redirect(new URL('/login', req.nextUrl))
}
// 6. Redirect to /dashboard if the user is authenticated
if (
isPublicRoute &&
session?.user &&
!req.nextUrl.pathname.startsWith('/')
) {
return NextResponse.redirect(new URL('/dashboard', req.nextUrl))
}
return NextResponse.next()
}
// Routes Middleware should not run on
export const config = {
matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
}