Search code examples
javascriptnext.jsmiddlewarenextjs-dynamic-routing

NextJs 14: Do i need to mention every protected route in the middleware file inside matcher?


So here is my middleware file -

import { NextResponse } from "next/server";
import { NextRequest } from "next/server";
import { getApiAuth } from "./app/middleware/api/auth";

const validateApi = (req: Request) => {
    const isValid = getApiAuth(req);

    if (!isValid)
        return new NextResponse(
            JSON.stringify({
                message: "Un-authorized",
            }),
            {
                status: 401,
            }
        );
};

// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
    console.log("Cookie", request.cookies);
    const isApiPath = request.nextUrl.pathname.startsWith("/api");

    if (isApiPath) {
        return validateApi(request);
    }

    return NextResponse.next();
}


export const config = {
    matcher: "/((?!api/login|_next/static|_next/image|favicon.ico).*)",
};

Is there any way to generate matcher regex dynamically with help of JS or some shorthand way to project the route. I wanted to configure matcher variable such a way that i have to write less code to protect the routes and also able to mention public route.


// '/((?!api|_next/static|_next/image|favicon.ico).*)', -|


const publicRoutes = [
    "api/login",
    "_next/static",
    "_next/image",
    "favicon.ico",
];

export const config = {
    matcher: `/((?!${publicRoutes.join("|")}).*)`,
};

Solution

  • I can generate an array of public routes and match them with requested route in the middleware

    export const publicAppRoutes = ["/login", "/getting-started", "/reset-password"]
    
    export const checkAuthForAppRoute = async (request: NextRequest, token: JWT | null) => {
    const url = new URL(request.url);
    const path = url?.pathname
    
    const isPublicPath = publicAppRoutes.find(p => path.startsWith(p))
    
    if (isPublicPath) {
        console.log("FOUND PUBLIC APP ROUTE PATH (skipping authorization check)")
        return true
    }
    
    if (!token) return false
    
    if (!token?.user) return false
    
    return true
    }