0
0
NextjsHow-ToBeginner · 4 min read

How to Use Middleware for Authentication in Next.js

In Next.js, use the middleware.ts file to run code before requests reach your pages. You can check authentication by reading cookies or headers inside middleware and redirect unauthenticated users with NextResponse.redirect(). This protects routes globally or selectively.
📐

Syntax

The middleware.ts file exports a middleware function that receives a NextRequest object and returns a NextResponse. You can inspect cookies or headers to check authentication and decide to continue or redirect.

  • NextRequest: Represents the incoming request, lets you read cookies, headers, and URL.
  • NextResponse: Used to continue the request or redirect.
  • NextResponse.redirect(url): Redirects the user to a different page.
typescript
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')?.value;

  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ['/protected/:path*'],
};
💻

Example

This example middleware protects all routes under /protected. It checks for a token cookie. If missing, it redirects to /login. Otherwise, it allows access.

typescript
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')?.value;

  if (!token) {
    // Redirect unauthenticated users to login
    return NextResponse.redirect(new URL('/login', request.url));
  }

  // Allow authenticated users to continue
  return NextResponse.next();
}

// Apply middleware only to /protected routes
export const config = {
  matcher: ['/protected/:path*'],
};
Output
When visiting /protected or any subpath, unauthenticated users are redirected to /login; authenticated users see the protected content.
⚠️

Common Pitfalls

  • Not specifying matcher in config causes middleware to run on all routes, which may slow your app.
  • Forgetting to check cookies or headers correctly can cause false authentication results.
  • Using client-side redirects instead of middleware redirects delays protection and exposes content briefly.
  • Not handling public routes separately can block access unintentionally.
typescript
/* Wrong: Middleware runs on all routes and redirects without matcher */
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')?.value;
  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  return NextResponse.next();
}

/* Right: Use matcher to limit middleware to protected routes */
export const config = {
  matcher: ['/protected/:path*'],
};
📊

Quick Reference

ConceptDescription
middleware.tsFile where middleware function is defined
NextRequestObject representing the incoming request, used to read cookies and URL
NextResponse.next()Continue request to the next handler or page
NextResponse.redirect(url)Redirect user to another URL
config.matcherSpecify which routes middleware applies to

Key Takeaways

Use middleware.ts to run code before requests reach pages in Next.js.
Check authentication by reading cookies or headers inside middleware.
Redirect unauthenticated users with NextResponse.redirect() to protect routes.
Limit middleware scope using config.matcher to avoid slowing all routes.
Always test middleware to ensure it correctly protects intended routes.