Search code examples
node.jsexpresssessioncookiesnetlify

Unable to set cookie for sub domain with express & Netlify proxy redirect


I'm not seeing set-cookie on callbacks with successful authentication on my deployed app, whereas I have success locally (verified session creation, auth successful, withCredentials, etc).

My node.js service is using passport w/ express session at say https://api.example.com, and an angular app at https://app.example.com. My angular app is currently deployed with Netlify, and I'm using redirects to forward requests to my api:

[[redirects]]
  from = "/api/*"
  to = "https://api.example.com/:splat"
  status = 200
  force = true
  headers = {X-From = "Netlify"}

[[headers]]
  for = "/api/*"
  [headers.values]
    Access-Control-Allow-Origin = "https://app.example.com"
    Access-Control-Allow-Credentials = "true"
    Access-Control-Expose-Headers = "Set-Cookie"

my express-session config:

  session: {
    secret: process.env.SESSION_SECRET || "dummy-super-secret",
    resave: false,
    saveUninitialized: false,
    cookie: {
      domain: ".example.com",
      secure: process.env.NODE_ENV === "production",
      sameSite: (process.env.NODE_ENV === "production" ? "none" : "lax") as
        | "none"
        | "lax",
      httpOnly: true,
      maxAge: 24 * 60 * 60 * 1000, // 24 hours
    },
  },
};

My express api sits behind a caddy reverse-proxy... currently with this config:

api.example.com {
  # Enable request logging
  log {
    output stdout
    format console
    level INFO
  }

  # bun-app:8080 is the docker container running the Node.js application
  reverse_proxy bun-app:8080  {
    header_up Host {host}
    header_up X-Real-IP {remote}
    header_up X-Forwarded-For {remote}
    header_up X-Forwarded-Proto {scheme}
    header_down Strict-Transport-Security max-age=31536000;
  }
}

Where is the delta? I would think with cross-origin cookies, I would see set-cookie on the response from my express-app when my client is redirected to https://app.example.com/api/auth/callback?code=8cdb3b467ba81738cb66


Solution

  • It seems the answer is as simple as reading the docs... I was crucially missing app.set("trust proxy", 1), thus my app was not interpreting the X-Forwarded-* headers.

    https://expressjs.com/en/guide/behind-proxies.html