Search code examples
node.jsreactjsexpressaxiosexpress-session

Express-session creates a new session every page load


I have a MERN web app with express-session which I'm trying to deploy to heroku. I configured the backend request using a proxy, by setting the proxy in the package.json file. It works as it should when both the front-end and back-end is running locally on localhost.

When I deploy the back-end to heroku, then after every browser refresh, express-session creates a new session/document in mongodb.

After a lot of debugging, it came out that setting axios.defaults.baseURL to the backend url was causing the issue. (I still don't know why.)

Apparently, setting the proxy in the package.json only works for development because when I deploy the app, the api's get called from the front-end url. So during development, when everything is running on localhost, and the proxy is set in package.json, then everything works well.

The problem is, when I set axios.defaults.baseURL. When I do that, then after every page reload, the session gets recreated.

What's the correct way to connect the front-end to the back-end?

Session.js

const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
const mongoose = require('mongoose');

module.exports = function(app) {
    var sess = {
        secret: 'mySecret',
        cookie: { token: null },
        saveUninitialized: false,
        resave: true,
        store: new MongoStore({ mongooseConnection: mongoose.connection })
    };

    if (app.get('env') === 'production') {
        app.set('trust proxy', 1);
        sess.cookie.secure = true;
    }

    app.use(session(sess));
};

Route.js

module.exports = function(app) {
    app.use(cors());
    app.use(helmet());
    require('../middleware/session')(app);
    // Other routes...
};

Solution

  • The way express-session works, is that it saves a reference cookie locally, and when you send a request, whether it's get, post, put, or delete, that request sends that cookie ref along with the request to the backend. Express-session then sees that cookie ref, goes and gets the corresponding data from the data store so that you can use it in your application.

    When setting axios.defaults.baseURL, the cookie doesn't get sent over from the local system to the backend. The way to send it, is by setting:

    axios.defaults.withCredentials = true;
    

    That makes sure the cookies get sent over. Once you set that, then you will have to set a specific origin with CORS, and you can't use '*'.