Search code examples
authenticationnext.jsjwtmiddlewarematcher

Nextjs - Middleware running on all paths instead of path defined by matcher


Nextjs version: 14.1.0 (app router)

The Problem

I have a middleware.ts file that I'm using to validate a jwt on only the /account route. I've used the config variable to define a matcher and passed in /account as a property, however, my middleware runs on every route I navigate to instead of only /account.

Here's my code:

import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";

export async function middleware(request: NextRequest) {
    const jwt = request.cookies.get("jwt")?.value;
    if (!jwt) return NextResponse.redirect(new URL("/login", request.url));
    const isValid = await validateJwt(jwt);
    if (!isValid) return NextResponse.redirect(new URL("/login", request.url));
}

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

I have verified the fact that it's running on every route by using logs and by seeing it hit my auth endpoint (from the validateJwt() function) on every navigation.

Oddly enough, it works completely fine when I use a path like /api/:path*, which only runs when I call one of my apis.

Worst comes to worst, I have the middleware run on every route and conditionally check the path before running the code, but it seems like this should be working.

Thank you for the help!!


Solution

  • It's crazy how quickly I figured it out - right after giving up and posting the question on StackOverflow. 🤦

    For anybody who's facing the same problem, the issue was with the <Link /> component from next/link prefetching the /account route on every route, because a link to /account lived in my navbar.

    To disable prefetching, you add these lines to your matcher:

    export const config = {
        matcher: [
            {
                source: "/account",
                missing: [
                    { type: "header", key: "next-router-prefetch" },
                    { type: "header", key: "purpose", value: "prefetch" },
                ],
            },
        ],
    };
    

    Taken straight from the Next.js docs: https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher

    Oops. I hope this helps somebody else!