Matúš Ravas
Matúš Ravas

Reputation: 73

NextJS access httponly cookie before each fetch request on external API

In my NextJS app I use external API for user authentication and processing other API calls. I use Flask app as an external API. When login is performed to the NextJS app I sent credentials to API and after user is authenticated, API responses with Set-Cookie header containing jwt access token. The cookie is set as httponly (I also tried not setting the cookie as httponly, but the result was same). The token is successfully set as it is visible in dev tools cookies section. I have the middleware function which controls every endpoint of the NextJS app if the user is authenticated. I am able to access cookies (even the httponly) inside the middleare.ts file, within the NextRequest object such as: req.cookies.get('token')?.value.

Example of middleware function in middleware.ts file, where cookies are accessible:

export function middleware(req: NextRequest) {
  const token = req.cookies.get('token')?.value // prints the token cookie value as expected
  //...rest of the code
}

However, I am trying to create built-in fetch wrappers, in my example case POST function defined inside ./fetch folder. This POST function is called from inside specific functions representing different API calls e.g:

import { POST } from "./fetch";

export async function somePingApiFetch(authData: User | PKI): Promise<SignInResult> {
  const result = await POST<SignInResult, User| PKI>('/ping', authData);
  return result;
}

The POST function is defined like so:

import {getCookie} from "cookies-next"

export async function POST<T, U>(endpoint: string | URL, body: U, options?: any): Promise<T> {
    const token = getCookie('token')
    console.log(token) // undefined
    const url = new URL(endpoint, 'http://localhost:5000/api/v1')
    const response = await fetch(url, {
        method: "POST",
        mode: "cors",
        cache: "no-cache",
        credentials: "same-origin",
        headers: {
            "Content-Type": "application/json",
            // ...(token && {"Authorization": `Bearer ${token}`})
        },
        redirect: "follow",
        referrerPolicy: "no-referrer",
        ...options,
        body: JSON.stringify(body)
    });
    return response.json();
}

As you can see, in the commented out section, I am trying to access httponly cookie using cookies-next library, I also tried js-cookie and cookies library and none was able to access the cookie, no matter if the cookie is httponly or not... I need the cookie to use it to set Authorization Bearer header.

I am calling the somePingApiFetch and similary defined functions from components marked as use client as well as server components. In none I am able to access the token data from cookies inside somePingApiFetch function.

Can someone please try to help and explain what am I doing wrong?

Upvotes: 2

Views: 1207

Answers (1)

dimonD
dimonD

Reputation: 304

I could be wrong, but I think you have to make sure that you have 'use server' in a file where you use your fetch request middleware function to tell Next.Js is a server side, so then you can access cookie using next js import { cookies } from 'next/headers'

In my case I have following function where I'm able to read httpOnly cookie and send it with Authorization headers.

 'use server'
    const cookieStore = cookies()
    const accessToken =cookieStore.get(localStorageKeys.accessToken)

    export const getPrices = async () => {
   const response = await 
   fetch(`${appConfig.BASE_URL}${apiEndPoints.prices}`, {
    cache: 'force-cache',
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
       Authorization: `Bearer ${accessToken?.value}`,
       },
     })
 //other stuff
  }

Upvotes: 0

Related Questions