6
votes

My app is divided between Client and Server. Client is a frontend side Nextjs app hosted on Now.sh, Server is its backend created with Express and hosted on Heroku, so the domains are client-app.now.sh and server-app.herokuapp.com .


Authentication

Authentication system is based on cookies and I'm using express-session to achieve it. This is my express-session configuration

app.use(
  session({
    store:
      process.env.NODE_ENV === "production"
        ? new RedisStore({
            url: process.env.REDIS_URL
          })
        : new RedisStore({
            host: "localhost",
            port: 6379,
            client
          }),
    name: "sessionID",
    resave: false,
    saveUninitialized: false,
    secret: keys.SESSION,
    unset: "destroy",
    cookie: {
      domain:
        process.env.NODE_ENV === "production"
          ? ".client-app.now.sh"
          : "localhost",
      secure: process.env.NODE_ENV === "production",
      httpOnly: true,
      maxAge: 7 * 24 * 60 * 60 * 1000
    }
  })
);

Cors is set with the "cors" package:

app.use(
  cors({
    origin:
      process.env.NODE_ENV === "production"
        ? process.env.CLIENT_URL
        : "http://localhost:3000",
    credentials: true
  })
);

Client is configured with Apollo and "credentials" in HttpLink is set to "include".

The problem is that cookie with session ID is correctly set in development, but not in production. Could this be related to the fact that I'm hosting client and server on different domains?

2
I have the same issue. I host my App on Heroku + my NodeJS Server on Heroku. On localhost cookie was set fine but since I host it on Heroku it wont set cookies anymore. I recognized that the req.session.cookie is set in NodeJS but no cookie is set on clients browser - Jonathan
@Jonathan my problem was identical to this: github.com/expressjs/session/issues/600 . During this days I tried pushing frontend on Heroku too, but it didn't work, so my last attempt was to use a custom Nextjs server as the main server also for backend and without any additional configuration it worked! TL;DR: I had client and server divided with their own servers. I used client server as the backend too and hosted it on Heroku (so with only one domain) and now cookies works. Different subdomains gave me the problem. - The_Wolf
BTW i am happy to say this: I SOLVED THIS ISSUE! Maybe it sounds weird but just remove the domain of your cookie. So just dont set a domain for your cookie! This worked for me :) - Jonathan

2 Answers

6
votes

I had my production node server behind a reverse proxy. This causes node to not trust the proxy and thus not set cookies.

I had to enable trusting the first proxy when in production.

app.set('trust proxy', 1) // trust first proxy

More info check out express-session's docs on the topic.

4
votes

After a lot of time trying to solve this, I just found the solution:

So I had,

app.use(session({
  secret: secret,
  saveUninitialized: false,
  resave: false,
  cookie: { 
    domain: clientDomain,
    secure: true
}
}));

I removed all the cookie object and this solved my issue:

app.use(session({
  secret: secret,
  saveUninitialized: false,
  resave: false
}));

Browsers seems don't need help to get the cookies.