Search code examples
javascriptcookiesauthorizationfetch-apinext.js13

How to send cookies with Fetch API in Next.js 13.4 middleware for authorization?


Since Axios cannot be used in Next.js 13.4 middleware, I attempted to implement authorization using the Fetch API. However, I am facing difficulties in sending cookies with Fetch. I am aware that Fetch does not send cookies to the server by default, so I included the option credentials: include, but it is still not functioning. Below, you can find the source code for the Next.js middleware and the CORS configuration from the Nest.js backend. I came across a similar question, but unfortunately, it does not provide a solution to my problem.Next.js does not send cookies with fetch request even though credentials are included

import { NextResponse } from "next/server";
    import type { NextRequest } from "next/server";
    const getUserRole = async function () {
      try {
        const res = await fetch("http://localhost:8080/auth/me", {
          method: "GET",
          headers: {
            Accept: "application/json",
            "Content-Type": "application/json",
          },
          credentials: "include",
        });
        if (res && res.status === 200) {
          return res.json();
        } else {
          console.error("Request failed");
        }
      } catch (error) {
        console.error('Request to "auth/me" failed', error);
      }
    };
    
    export function middleware(request: NextRequest) {
      const path = request.nextUrl.pathname;
      const isPublicPath =
        path === "/auth/login" || path === "/auth/register" || path === "/";
      const token = request.cookies.get("access_token")?.value || "";
    
      if (isPublicPath && token && path !== "/") {
        return NextResponse.redirect(new URL("/", request.nextUrl));
      }
    
      if (!isPublicPath && !token) {
        return NextResponse.redirect(new URL("/auth/login", request.nextUrl));
      }
    
      if (!isPublicPath && token) {
        console.log("tokkk :", token);
        getUserRole().then((res: any) => {
          console.log("role ::", res);
        });
      }
    }
    
    export const config = {
      matcher: ["/", "/auth/login", "/auth/register", "/dashboard"],
    };

 app.enableCors({
    origin: 'http://localhost:3000',
    allowedHeaders: [
      'Content-Type',
      'Authorization',
      'X-Requested-With',
      'X-HTTP-Method-Override',
      'Content-Type',
      'Accept',
      'Observe',
      'Access-Control-Allow-Credentials',
      'Access-Control-Allow-Origin',
      'Access-Control-Allow-Headers',
    ],
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
    credentials: true,
  });

Solution

  • The middleware function in nextjs, will run only on the server. and as you know, there is not any cookie system on the server like in the browser. so, credentials: "include" will not work. Therefore, you need to re-assign the authorization token to the header of the fetch request. like so:

    export async function middleware(request: NextRequest) {
        const token = request.cookies.get("access_token")?.value || "";
    
        const res = await fetch("http://localhost:8080/auth/me", {
            headers: {
                Authorization: token
            }
        })
    
        ...
    }
    

    you can find more information of the fetch() function in Mozilla documentation https://developer.mozilla.org/en-US/docs/Web/API/fetch