title: Express session doesn't persist if the client is on a different domain
body: <p><strong>tl:dr;</strong></p>
  <p>A Node (express) server is hosted on Heroku, and the UI is hosted on Netlify. When the UI makes a REST API call to the server, the session doesn't persist (but it persists if I ran both locally. <code>localhost:5000</code> on the server, <code>localhost:3000</code> on UI. The UI is proxying requests with <code>package.json</code>).</p>
  <p><strong>Code snippets</strong></p>
  <p><code>session.ts</code></p>
  <pre><code>export const sessionConfig = {
    secret: process.env.SESSION_KEY,
    store: new RedisStore({ client: redisClient }),
    resave: true,
    saveUninitialized: true,
    cookie: {
      secure: process.env.NODE_ENV === 'production',
      sameSite: process.env.NODE_ENV === &quot;production&quot; ? 'none' : 'lax',
    },
  };
  </code></pre>
  <p><code>server.ts</code></p>
  <pre><code>const app = express();
  
  app.use(express.json());
  app.use(cookieParser());
  
  app.set('trust proxy', 1);
  app.use(session(sessionConfig)); // This sessionConfig comes from the file above
  
  app.use(cors({
    credentials: true,
    origin: process.env.CLIENT_URL,
  }));
  </code></pre>
  <p>I googled something like <code>express session not persist when cross domain request</code>. Then, I saw threads like <a href="https://stackoverflow.com/questions/33958907/express-session-not-persisting-after-cors-calls">this</a> and <a href="https://stackoverflow.com/questions/9071969/using-express-and-node-how-to-maintain-a-session-across-subdomains-hostheaders">this</a>. It seems that <code>app.set('trust proxy', 1)</code> will make sure that session data will be persisted for cross-domain requests. Apparently, in my case, something is still missing.</p>
  <p>Does anyone see what I'm doing wrong? Any advice will be appreciated!</p>
  <p><strong>PS:</strong></p>
  <p>I'm using sessions for captcha tests, which looks like...</p>
  <p><code>captch.ts</code></p>
  <pre><code>CaptchaRouter.get('/api/captcha', async (req: Request, res: Response) =&gt; {
    const captcha = CaptchaService.createCaptcha();
    req.session.captchaText = captcha.text;
    res.send(captcha.data);
  });
  
  CaptchaRouter.post('/api/captcha', async (req: Request, res: Response) =&gt; {
      if (req.session.captchaText !== req.body.captchaText) {
        throw new BadRequestError('Wrong code was provided');
      }
  
      // The client sent the correct captcha
    },
  );
  
  </code></pre>
  <p><strong>Another PS:</strong>
  Here's how the response heders look like:</p>
  <pre><code>Access-Control-Allow-Credentials: true
  Access-Control-Allow-Origin: https://example.netlify.app
  Connection: keep-alive
  Content-Length: 46
  Content-Type: application/json; charset=utf-8
  Date: Sun, 09 Jan 2022 00:00:00 GMT
  Etag: W/&quot;2e-cds5jiaerjikllkslaxmalmird&quot;
  Server: Cowboy
  Set-Cookie: connect.sid=s%3ramdon-string-here; Path=/; Expires=Sun, 09 Jan 2022 00:00:00 GMT; HttpOnly; Secure; SameSite=None
  Vary: Origin
  Via: 1.1 vegur
  X-Powered-By: Express
  </code></pre>