title: Cross-Domain Session Cookie (Express API on Heroku + React App on Netlify)
body: <p>I have a React App making calls to an API in node.js/Express.</p>
  <p>Frontend is deployed in Netlify (https), Backend deployed on Heroku (https).</p>
  <p>My problem:</p>
  <ul>
  <li>Everything working in dev environment (localhost)</li>
  <li>In production (Netlify/Heroku), the api calls to register and login seem to work but the <strong>session cookie is not stored in the browser</strong>. Because of that, any other calls to protected routes in the API fail (because I don't receive the user credentials).</li>
  </ul>
  <p>             <a href="https://i.stack.imgur.com/kZO7J.png" rel="noreferrer"><img src="https://i.stack.imgur.com/kZO7J.png" alt="cross-domain authentication cookie react express" /></a></p>
  <p><br /><br /><br /></p>
  <p><em>Talking is cheap, show me the code....</em></p>
  <h3>Backend (Express API):</h3>
  <ul>
  <li>I'm using <a href="https://www.npmjs.com/package/passport" rel="noreferrer">passport</a> (local strategy), <a href="https://www.npmjs.com/package/express-session" rel="noreferrer">express-session</a>, <a href="https://www.npmjs.com/package/cors" rel="noreferrer">cors</a>.</li>
  </ul>
  <p><strong>App.js</strong></p>
  <pre class="lang-js prettyprint-override"><code>require('./configs/passport');
  
  // ...
  
  const app = express();
  
  // trust proxy (https://stackoverflow.com/questions/64958647/express-not-sending-cross-domain-cookies)
  app.set(&quot;trust proxy&quot;, 1); 
  
  app.use(
    session({
      secret: process.env.SESSION_SECRET,
      cookie: {
        sameSite: process.env.NODE_ENV === &quot;production&quot; ? 'none' : 'lax',
        maxAge: 60000000,
        secure: process.env.NODE_ENV === &quot;production&quot;,
      },
      resave: true,
      saveUninitialized: false,
      ttl: 60 * 60 * 24 * 30
    })
  );
  
  app.use(passport.initialize());
  app.use(passport.session());
  
  // ...
  
  
  app.use(
    cors({
      credentials: true,
      origin: [process.env.FRONTEND_APP_URL]
    })
  );
  
  //...
  
  app.use('/api', require('./routes/auth-routes'));
  app.use('/api', require('./routes/item-routes'));
  
  
  </code></pre>
  <p><strong>CRUD endpoint (ex. item-routes.js):</strong></p>
  <pre class="lang-js prettyprint-override"><code>// Create new item
  router.post(&quot;/items&quot;, (req, res, next) =&gt; {
      Item.create({
          title: req.body.title,
          description: req.body.description,
          owner: req.user._id // &lt;-- AT THIS POINT, req.user is UNDEFINED
      })
      .then(
          // ...
      );
  });
  
  </code></pre>
  <h3>Frontend (React App):</h3>
  <ul>
  <li>Using Axios with the option &quot;withCredentials&quot; set to true...</li>
  </ul>
  <p><strong>User registration and login:</strong></p>
  <pre class="lang-js prettyprint-override"><code>class AuthService {
    constructor() {
      let service = axios.create({
        baseURL: process.env.REACT_APP_API_URL,
        withCredentials: true
      });
      this.service = service;
    }
    
    signup = (username, password) =&gt; {
      return this.service.post('/signup', {username, password})
      .then(response =&gt; response.data)
    }
  
    login = (username, password) =&gt; {
      return this.service.post('/login', {username, password})
      .then(response =&gt; response.data)
    }
     
    //...
  }
  </code></pre>
  <p><strong>Creating a new item...:</strong></p>
  <pre><code>    axios.post(`${process.env.REACT_APP_API_URL}/items`, {
          title: this.state.title,
          description: this.state.description,
      }, {withCredentials:true})
      .then( (res) =&gt; {
          // ...
      });
  </code></pre>