DEV Community

Cover image for Next.js middleware to assist with routing
Osmar Faria
Osmar Faria

Posted on

Next.js middleware to assist with routing

When it comes to protecting routes and controlling access in Next.js, various methods exist. However, Next.js middleware provides a straightforward way to achieve this. Let's explore an example based on the Next.js documentation.

To get started, create a middleware.js (or .ts) file at the root of your project, at the same level as your app and pages directories (or inside src if applicable).

import { NextResponse } from "next/server";

// This function can be marked `async` if using `await` inside
export default function middleware(request) {
  return NextResponse.redirect(new URL("/", request.url));
}

export const config = {
  matcher: "/dashboard",
};


Enter fullscreen mode Exit fullscreen mode

In this example, if a user attempts to access the /dashboard page, they will be redirected to the home / page. The matcher allows you to filter specific paths, and it can handle single or multiple paths. You can even use regular expressions for more complex matches.

export const config = {
  matcher: ['/about/:path*', '/dashboard/:path*'],
}
Enter fullscreen mode Exit fullscreen mode
export const config = {
  matcher: [
   '/((?!api|_next/static|_next/image|favicon.ico).*)',
  ],
}
Enter fullscreen mode Exit fullscreen mode

Now, let's consider situations where you need different rules for specific scenarios, such as when a user is already logged in and tries to access the login page, or when a user is logged in but lacks the credentials to access the dashboard page.

For such cases, you can leverage middleware to customize your access control. Here's an example using the next-auth library for authentication, where we check the user's login status using the getToken function.


// middleware.ts
import { getToken } from 'next-auth/jwt'
import { NextRequest, NextResponse } from 'next/server'

export async function middleware(req: NextRequest) {
  const homeUrl = new URL('/', req.url)
  const pathname = req.nextUrl.pathname
  const loginPathname = /login/i

  const isLoginPathname = loginPathname.test(pathname)
  const token = await getToken({ req })

  if (isLoginPathname) {
    if (token)
      return NextResponse.redirect(homeUrl)
    }
  }

  return NextResponse.next()
} 

Enter fullscreen mode Exit fullscreen mode

In this example, if a logged-in user tries to access the login page, they will be redirected to the home page.

Next, let's consider a scenario where you want only administrators to access the dashboard page. To simplify this example, we'll check an isAdmin property in the user's token obtained from next-auth.

// middleware.ts
import { getToken } from 'next-auth/jwt'
import { NextRequest, NextResponse } from 'next/server'

export async function middleware(req: NextRequest) {

  const pathname = req.nextUrl.pathname
  const adminPathname = /dashboard/i
  const homeUrl = new URL('/', req.url)


  const isAdminProtected = 
  adminPathname.test(pathname)

  const token = await getToken({ req })

  if (isAdminProtected) {
    if (!token || !token.isAdmin) {
      return NextResponse.redirect(homeUrl)
    }
  }

  return NextResponse.next()
}

Enter fullscreen mode Exit fullscreen mode

In this case, only users with the isAdmin property set in their token will be able to access the dashboard page. Otherwise it will be redirected to the homepage /.

By using Next.js middleware, you can easily customize route protection and access control in your web applications.

Top comments (0)