Skip to main content

Proxy - middleware

Proxy (formerly called middleware) in Next.js allows you to run code between a client HTTP request and your route handler. It acts as a checkpoint or filter that can:

  • Intercept and inspect the request

  • Verify authentication (session/token)

  • Enforce authorization rules

  • Modify or reject the request before it reaches the server endpoint

tip

Proxy is where route-level authorization happens — ensuring that only permitted users can access protected parts of your application.

proxy
proxy executes before a request reaches the route handler

Access Control

Proxy is commonly used in to:

  • Verify user sessions (authentication)

  • Check roles or permissions (authorization)

  • Redirect unauthenticated requests

  • Prevent unauthorized access

If a request is authorized, we allow it to continue.
If not, we redirect or reject the request.

middleware.ts renamed to proxy.ts

The middleware.ts file was renamed to proxy.ts with version 16 of Next.js.

restricted items routes
restricted routes for items: create, update, delete

Proxy setup

In a Nextjs application, we set up proxy by creating a file called proxy.ts at the project root.

proxy.ts
import { NextResponse } from "next/server";
import { auth } from "@/auth";

export default auth((request) => {
const { pathname } = request.nextUrl;

const isAuthenticated = !!request.auth?.user;

const publicPaths = ["/", "/show-item", "/show-items", "/api/items"];

if (!isAuthenticated && !publicPaths.includes(pathname)) {
return NextResponse.redirect(new URL("/", request.url));
}

return NextResponse.next();

});

export const config = {
matcher: [
"/create-item/:path*",
"/update-item/:path*",
"/delete-item/:path*",
],
};

Here's a breakdown:

  1. auth((request) => { ...})
  • wraps the proxy function
  • retrieves the session
  • attaches the session to request.auth
  1. request.auth?.user :
  • contains the authenticated user (if logged in)
  • undefined if not authenticated
  1. Route protection logic
  • If user is not authenticated -> redirect
  • Otherwise -> allow request to continue
  1. NextResponse.next()
  • Allows the request to proceed to the route handler

Matcher

The matcher controls which routes the proxy will be applied to. It acts as a filter, ensuring that the proxy only executes for specific paths or patterns.

export const config = {
matcher: [
"/create-item/:path*",
"/update-item/:path*",
"/delete-item/:path*",
],
};

The above ensures:

  • Proxy runs only for matching routes
  • Skips all other routes

Matcher example:

"/create-item/:path*"

Matches:

  • /create-item
  • /create-item/123
  • /create-item/edit
info

Without a matcher, proxy would run on every request. This affects performance and behavior. With a matcher, you target only protected routes and public routes remain unaffected.