Next.js middleware to assist with routing
Tags: nextjs, routing, middleware, development
Published: 2023-10-26 16:43:04

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).

```javascript
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",
};


```

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.

```javascript
export const config = {
  matcher: ['/about/:path*', '/dashboard/:path*'],
}
```

```javascript
export const config = {
  matcher: [
   '/((?!api|_next/static|_next/image|favicon.ico).*)',
  ],
}
```
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.

```javascript

// 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()
} 

```

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.

```javascript
// 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()
}

```

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.