Issues setting cookies in express and React application from google auth

I’ve encountered an issue while attempting to set cookies following successful login through Google authentication within my Node.js application. This application utilizes Google’s OAuth2 authentication flow to allow users to log in securely via their Google accounts. Upon successful authentication, the application should set cookies containing authentication tokens and user information before redirecting the user to the appropriate page.

The authentication process consists of several steps: when a user logs in using their Google account, they are redirected to Google’s authentication page, where they authenticate and authorize the application to access their information. Upon authorization, Google redirects the user back to the application’s callback URL along with an authentication code.

In the callback function, which handles this redirect, the application exchanges the authentication code for an access token by making a request to Google’s OAuth2 token endpoint (https://oauth2.googleapis.com/token). This token allows the application to retrieve the user’s information, such as email, name, and profile picture, from Google’s servers.

Following the user’s profile creation or update, the application generates JWT (JSON Web Token) authentication tokens for the user and a refresh token for future token refreshing. These tokens are then set as cookies in the HTTP response headers using the Set-Cookie header and the res.cookie() method provided by the Express framework.

Despite following due process and confirming that both the callback and initialization functions are functioning correctly, I’ve encountered an issue where the cookies containing the authentication tokens and user information are not being set before redirecting the user. This issue prevents users from being properly authenticated and accessing protected resources within the application.

Below is a snippet of the callback function responsible for handling the Google authentication:

googleSignUpCallback: RequestHandler = catchAsync(async (req, res, next) => {
    const { code } = req.query;

    const tokenUrl = 'https://oauth2.googleapis.com/token';
    const params: any = {
      code,
      client_id: ENV.GOOGLE_CLIENT_ID,
      client_secret: ENV.GOOGLE_CLIENT_SECRET,
      redirect_uri: ENV.GOOGLE_REDIRECT_URI,
      grant_type: 'authorization_code',
    };

    const response = await axios.post(tokenUrl, querystring.stringify(params), {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
    });

    const { id_token } = response.data;

    const { email, email_verified, picture, name } = jwt.decode(
      id_token,
    ) as JwtPayload;

    if (!email_verified) {
      return next(new AppError('Google account is not verified', 403));
    }

    const user = await User.findOneAndUpdate(
      { email: email },
      {
        email: email,
        name: name,
        image: picture,
        isEmailConfirmed: true,
      },
      { upsert: true, new: true },
    );

    this.createAndSendToken(user, 201, res, false);
    res.redirect(ENV.FRONTEND_URL);
  });

createAndSendToken = (
    user: any,
    statusCode: number,
    res: Response,
    sendRes: boolean,
  ) => {
    const token = this.signToken({ id: user.id, email: user.email });
    const refreshToken = this.signToken({ id: user.id }, true);
    const cookieExpireTime = ENV.JWT_COOKIE_EXPIRES_IN;

    // check if cookie expire time is available
    if (!cookieExpireTime)
      return new AppError('Cookie expire time not found', 400);

    // set cookie options
    const cookieOptions: ICookieOption = {
      maxAge: 900000,
      httpOnly: false,
      sameSite: 'none',
      secure: false,
    };

    // sends a secure jwt token to the browser that would be sent back to us upon every request
    // if (ENV.NODE_ENV === 'production') cookieOptions.secure = true;

    res.set('Set-Cookie', [token, refreshToken]);
    res.cookie('jwt', token, cookieOptions);
    res.cookie('refreshToken', refreshToken, cookieOptions);

    // this makes the password and active not show in the response it send to the browser
    user.password = undefined;

    if (sendRes) {
      return res.status(statusCode).json({
        status: 'success',
        token,
        refreshToken,
        user,
      });
    }
  };