Express [Nest.js] - res.cookie() not set in Heroku production

Viewed 264

I am using Next.js (Frontend) and Nest.js (Backend) Frameworks and I am having issues with a HTTP Cookies. The following code works in development trough localhost, but not when publishing the code to vercel (Next.js) and Heroku (Nest.js)

Here is a snippet of my Nest.js Setup

// main.ts

  async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
    logger: new LoggerService(),
    cors: true,
  });
  app.use(cookieParser());
  app.enableCors({
    origin: ["<my-site>"], 
    credentials: true,
  });
...

  await app.listen(process.env.PORT || 5000);
}
bootstrap();

Here is my Route:

@Post("login/verify")
  @HttpCode(201)
  @ApiResponse({ description: "returns JWT for verified login attempt" })
  async verify(
    @Body() method: VerificationDto,
    @Req() req: Request,
    @Res({ passthrough: true }) res: Response
  ) {
    const { accessToken } = await this.userService.verifyLogin(method);
    const origin = req.get("origin");
    this.loggerService.log(`origin: ${origin}`);

    res
      .set("Access-Control-Allow-Credentials", "true")
      .set("Access-Control-Allow-Origin", origin)
      .cookie("accessToken", accessToken, {
        expires: new Date(new Date().getTime() + 60 * 1000 * 60 * 2),
        sameSite: "none",
        secure: true,
        httpOnly: false,
      });

    return {
      accessToken,
      refreshToken,
    };
  }

Here is my useAuth component in Next.js

import React from "react";
import jwtDecode from "jwt-decode";
import nookies from "nookies";
import { redirect } from "../../services/redirect";
import { GetServerSideProps, NextPage } from "next";

export interface User {
  accessToken: string;
  email: string;
  exp: number;
  iat: number;
  id: string;
  name: string;
  roles: Array<string>;
}

const AuthContext = React.createContext<User>(null as unknown as User);

const loginRoute = `/login`;

export const authenticate = (
  getServerSidePropsInner: GetServerSideProps = async () => ({ props: {} })
) => {
  const getServerSideProps: GetServerSideProps = async ctx => {
    const { req, res } = ctx;

    if (!req.headers.cookie) {
      console.log("no cookie found");
      redirect(ctx, loginRoute);
      return { props: {} };
    }
    const { accessToken } = nookies.get(ctx);
    console.log(accessToken);
    let user = null;
    try {
      user = {
        accessToken,
        ...(jwtDecode(accessToken as string) as object),
      };
    } catch (e) {
      console.log(e);
      redirect(ctx, loginRoute);
    }

    const result = await getServerSidePropsInner(ctx);
    return {
      ...result,
      props: {
        user,
        //@ts-ignore
        ...result.props,
      },
    };
  };
  return getServerSideProps;
};

export const withAuth = (C: NextPage) => {
  const WithAuth = (props: any) => {
    const { user, ...appProps } = props;
    return (
      <AuthContext.Provider value={user}>
        <C {...appProps} />
      </AuthContext.Provider>
    );
  };

  WithAuth.displayName = `WithAuth(${C.displayName})`;
  return WithAuth;
};

export default withAuth;

export const useAuth = (): User => React.useContext(AuthContext);

I am using axios with the following login request

  verifyLogin: ({ code, email }: { code: string; email: string }) => {
    return axios(`${apiURI}/user/login/verify`, {
      method: `POST`,
      withCredentials: true,
      headers: {
        "Content-Type": "application/json",
      },
      data: {
        code: code,
        email: email,
      },
    });
  },

Setup works with localhost. It adds a http cookie which is read by the next.js application. However, when deploying my Nest.js app to Heroku, the cookie does not seem to send to the next application. I have tried adding different values for the CookieOptions

        sameSite: "none",
        secure: true,
        httpOnly: false,

However, this did not help either.

Any help is much appreciated as I am fighting with this for days.

0 Answers
Related