The Setup
I have setup a frontend environment using create-react-app. In this environment I use Axios to make a POST request to my Node JS Express Backend Server /login endpoint. I setup sessions middleware using express-sessions and storing the sessions in Redis. I have all this running in localhost currently.
Environment
React App - http://localhost:3005/kp (Note: the service runs on http://localhost:3005 however, all the routes have /kp in them)
Express Backend - http://localhost:5001
Redis - http://localhost:6379
What Works
When the frontend sends the request to the backend the Express server does it's thing and authenticates the user; it stores the username in the req.session.username (this is just as a test), Redis console shows that the key value store was successful, the frontend network tab shows a 200 status with a Set-Cookie response header and a tab that shows the cookie (screenshots below).
The Problem
Everything seems to be working fine but the cookie is not set in the Browser. I have refreshed the page, tried again many times and yet it will not set the cookie in any browser (Google Chrome & Safari). I am getting frustrated because it seems as though Chrome acknowledges that the Set-Cookie is present but ignores it for some reason.
What I've Tried
Axios
Backend
Code
React Frontend Axios POST Request
      axios.post('http://localhost:5001/login', loginBody, {
        headers: {
          'Content-Type': 'application/json'
        }
      },
        { withCredentials: true }
      )
        .then((res) => {
          console.log(res);
        })
        .catch((error) => {
          console.log(error);
          this.setState({
            errorMessage: `Server Error`,
            loading: false
          });
        });
Express Server
const express = require('express');
const http = require('http');
const cors = require('cors');
const socketServer = require('./src/sockets');
const bodyParser = require('body-parser');
const session = require('express-session');
const redis = require('redis');
const redisClient = redis.createClient();
const redisStore = require('connect-redis')(session);
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
const port = process.env.PORT || 5001;
const { loginRoutes } = require('./src/routers');
const app = express();
redisClient.on('error', (err) => {
  console.log('Redis error: ', err);
});
app.use(cors({
  origin: '*',
  methods: ['POST', 'PUT', 'GET', 'OPTIONS', 'HEAD'],
  credentials: true
}));
// Redis session storage setup
// API Docs for express-session: https://www.npmjs.com/package/express-session
const sessionMiddleware = session({
  secret: process.env.REDIS_SECRET || 'testing12345',
  name: 'session',
  resave: false,
  saveUninitialized: true,
  cookie: {
    secure: false
  },
  store: new redisStore(
    {
      host: process.env.REDIS_HOSTNAME,
      port: process.env.REDIS_PORT,
      client: redisClient,
      ttl: 604800
    }
  )
});
// Uses session middleware
app.use(sessionMiddleware);
app.use(bodyParser.json({ limit: '5mb' }));
const server = http.createServer(app);
// Starts Socket Server
socketServer(server, sessionMiddleware);
// Uses the routes from the router directory
app.use(loginRoutes);
server.listen(port, () => {
  console.log(`Listening on port: ${port}`);
});
Screenshots
Network Response

Request Cookie

Application Cookies

As you can see the cookie is missing in the list of browser cookies. I have a feeling it is something small but I have not been able to find anything.
I am not getting any errors in any service. Thank you in advance for your help.
Solution
As Michał Lach pointed out I put withCredentials in the wrong place in the Axios call.
Frontend Axios
  axios.post('http://localhost:5001/login', loginBody, {
    headers: {
      'Content-Type': 'application/json'
    },
    withCredentials: true
  })
However, once I did this I began to get CORS error. The CORS error was you cannot have a wildcard '*' in your Access-Control-Allow-Origin (origin) configuration. For this example I changed it to point only to http://localhost:3005; however, there are ways to do dynamic whitelists as documented here: https://www.npmjs.com/package/cors#configuring-cors-w-dynamic-origin
Backend
app.use(cors({
  origin: 'http://localhost:3005',
  methods: ['POST', 'PUT', 'GET', 'OPTIONS', 'HEAD'],
  credentials: true
}));
Once I made these changes the cookie started being set on the frontend correctly.
Are you sure, you are setting axios options correctly ?
You have :
    axios.post('http://localhost:5001/login', loginBody, {
    headers: {
      'Content-Type': 'application/json'
    }
  },
    { withCredentials: true }
  )
    .then((res) => {
      console.log(res);
    })
    .catch((error) => {
      console.log(error);
      this.setState({
        errorMessage: `Server Error`,
        loading: false
      });
    });
Try this:
    axios.post('http://localhost:5001/login', loginBody, {
    headers: {
      'Content-Type': 'application/json'
    },
    { withCredentials: true }
  }
        ....
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With