3

I am in a next-js app and my auth token is stored in cookies. For some raisons i use Swr and Api route to fetch my secured api backend. i am trying to find a way to put my auth token in all api request.

During login cookie is set

  res.setHeader(
        'Set-Cookie',
        cookie.serialize('token', data.access_token, {
          httpOnly: true,
          secure: process.env.NODE_ENV !== 'development',
          maxAge: data.expires_in, // 1 week
          sameSite: 'strict',
          path: '/',
        }),
      );

This is an example of a page using swr fetch

//page/test.ts - example of my test route

  const { data, error } = useFetchContent(id);

  if (error) {
    showError('error');
    replace('/');
  }

  return <DisplayContent content={data} />

This is a swrFetchHook

// fetchContentHook 

function useFetchContent(id: string): ContentDetail {
  return useSWR<any>(`/api/content/${id}`, fetcherApiRoute);
}
 
const fetcherApiRoute = (url: string): Promise<any> => {
  return axios(url)
  .then((r) => r.data)
  .catch((err) => {
    console.info('error is ', err)
    throw err
  });
};

export default useFetchContent;

inside api route


export default async (req, res): Promise<ContentDetail> => {
  const { id } = req.query;
  if (req.method === 'GET') {
   
    const fetchRealApi = await apiAxios(url);
   
  if(fetchRealApi) {
   // here depending on result of fetchRealApi i add some other fetch ... 
   return res.status(200).json({ ...fetchRealApi, complement: comp1 });
  }

  return res.status(500)

  }

  return res.status(500).json({ message: 'Unsupported method only GET is allowed' });
};


and finally api axios configuration


const apiAxios = axios.create({
  baseURL: '/myBase',
});

apiAxios.interceptors.request.use(
  async (req) => {

    // HERE i am trying to get token from cookies
    // and also HERE if token is expired i am trying to refresh token
    config.headers.Authorization = token;
    req.headers['Content-type'] = 'application/x-www-form-urlencoded';
    return req;
  },
  (error) => {
    return Promise.reject(error);
  },
);

export default apiAxios;

I am stuck here because i cant find token during apiAxios.interceptors.request.use... Did you know what i am doing wrong, and am i on a correct way to handle this behavior ?

vector
  • 63
  • 2
  • 6
  • Does this answer your question: [Why are cookies not sent to the server via getServerSideProps in Next.js?](https://stackoverflow.com/questions/69057271/why-are-cookies-not-sent-to-the-server-via-getserversideprops-in-next-js)? That question is about `getServerSideProps`, but the same applies to API routes, you should then be able to get the `token` in the interceptor from `req.headers['Cookie']`. – juliomalves Dec 08 '21 at 16:41

2 Answers2

1

To allow sending server cookie to every subsequent request, you need to set withCredentials to true. here is the code.

const apiAxios = axios.create({
  baseURL: '/myBase',
  withCredentials: true,
});
Nilesh Patel
  • 3,193
  • 6
  • 12
  • thanks i missed that part. And if i want to grab my refresh token inside axios interceptor. To renew my token if it is expired ? – vector Dec 08 '21 at 14:11
0

Nilesh's answer is right if your API is able to authorize requests based on cookies. Also it needs the API to be in the same domain as your frontend app. If you need to send tokens to the API (the one which is in the cookie), then you will need a small backend component often called BFF or Token Handler. It can extract the token from the cookie and put in an Authorization header.

At Curity we've created a sample implementation of such a Token Handler, of which you can inspire: https://github.com/curityio/kong-bff-plugin/ You can also have a look at an overview article of the Token Handler pattern.

Michal Trojanowski
  • 10,641
  • 2
  • 22
  • 41