Search code examples
typescriptcookiesnext.jsjwtnestjs

How can I make sure a cookie is set before using it?


I'm currently working on a JWT authorization code flow using Next.js and NestJS.

This is the POST request I'm sending from the front to the back.

const response = await fetch(
  'http://localhost:4000/auth/42/callback?code=' + code, { // code is received from the OAuth server
    method: 'POST',
    mode: 'cors',
    headers: {
      'Content-Type': 'application/json',
    },
    credentials: 'include',
  }
);

Once the backend receives the request, it will generate the JWT and send it back to the front using response.

@Post('42/callback')
async Callback(@Query('code') code: string, @Res({passthrough: true}) res) {
  if (!code) {
    res.status(400).send('Missing code');
    return;
  }

  try {
    const response = await this.authService.exchangeCodeForToken(code);
    const jwt = await this.authService.handleCallback(response);
    res.setHeader('Access-Control-Allow-Credentials', 'true');
    res.cookie('jwt', jwt, {
      sameSite: 'strict'
    });
    res.status(200).send();
  } catch (error) {
    console.error(error);
    res.status(500).send('Internal server error');
  }
}

The browser successfully sets the jwt cookie, however I'm unable to find a way to make sure it is set before using it. It seems that there is a small latency between the response and setting the cookie.

import jwtDecode from 'jwt-decode';
import { useCookies } from 'react-cookie';

const [ cookies ] = useCookies();

const jwt = cookies.jwt;
const jwtPayload: any = jwtDecode(jwt); // Here jwt is undefined

I've looked at the browser Network Profiler but I'm not able to see any latency. Browser network profiler


Solution

  • I've finally found a solution to my problem. Apparently, react-cookie is not reliable in some situations (see this issue or this one). The useCookies hook is not updating when a new cookie is added. While this issue isn't fixed the best workaround is to use universal-cookie instead.

    Here is what it will looks like:

    import Cookies from 'universal-cookie';
    import jwtDecode from 'jwt-decode';
    
    const cookies = new Cookies();
    const jwt = cookies.get('jwt');
    const decodedPayload = jwtDecode(jwt);