SamOlisa
SamOlisa

Reputation: 1

How can I match dynamic routes in NextJS middleware functions?

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?

Upvotes: 0

Views: 662

Answers (1)

SamOlisa
SamOlisa

Reputation: 1

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$).*)'],
}

Upvotes: 0

Related Questions