node.jsazuredockerhttpssamesite

How to pass sameSite: none from Dockerized Node app running on Azure AppService?


I have several Node applications that run in Docker containers hosted on Azure AppServices.

I'm trying to figure out how to deal with the SameSite cookie issue, but to do that I need https. At the moment, the Node/Express apps are running http inside the container, and then Azure is attaching our certificates to the AppService to run https.

We're using cookie-session with the following options:

app.use(
  cookieSession(
    {
      name: 'session',
      keys: [ '123456789ABCD' ],
      // Cookie Options
      maxAge:   24 * 60 * 60 * 1000,  // 24 hours
      httpOnly: true,
      sameSite: 'none',
      secure:   true
    }
  )
)

sameSite: 'none' and secure: true are new, but whenever I deploy the secure: true blows up my app, because I'm not running http inside the container, so the cookies get stripped.

I've also tried app.set('trust proxy', 1), but couldn't tell that it had any impact.

Dockerfile:

# Create a container image for the app
FROM node:erbium-alpine

# Allow NODE_ENV to be set to different values
# depending on the image build/deployment environment
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

# Create app directory
WORKDIR /usr/app

# Copy package.json and yarn.lock into app directory
COPY ./package.json ./
COPY ./yarn.lock ./

# Install backend NPM modules
RUN yarn install

# COPY the client package and yarn files into app
COPY ./client/package.json ./client/
COPY ./client/yarn.lock ./client/

# Install client NPM modules
RUN yarn run install:client

# COPY the rest of the files into app directory
COPY ./ ./

# build the client
RUN yarn run build:client

# Expose ports for accessing the app
EXPOSE 5000 80

# Launch the Express server
CMD ["node", "server.js"]

What's a good approach given this deployment scheme? Do I add some self signed cert into the container, or am I just missing a setting somewhere?

And then after I fix this for Azure, how do I run it in development?


Solution

  • In AppService, SSL termination happens at the network load balancers, so all HTTPS requests reach your app as unencrypted HTTP requests. But, SameSite=None must be securei.e. the cookie is only to be sent over HTTPS. If secure is set to true and Node.js is not directly over a TLS connection like in this case, you need to set trusted proxy properly so that X-Forwarded-* headers are passed and cookie is set correctly. Set the following during your express app bootstrapping.

    app.set('trust proxy', 2);
    

    You mentioned you tried app.set('trust proxy', 1) which means it's only for 1st hop. In this case we need 2 hops to include the ingress for the container apart from the network load balancer. For details refer this.

    And then after I fix this for Azure, how do I run it in development?

    If you set app.set('trust proxy', 2);, I believe you won't need any special treatment for local debugging.