Search code examples
javascriptnode.jsexpresscookiesexpress-session

Express Session Cookie (connect.sid) not being deleted from browser after destroying session


I have a Vue.js SPA and a Node.js API built with Express.js. I'm using express-session (^1.11.3) to manage sessions and express-sequelize-session (0.4.0) to persist the session on a Postgres DB through Sequelize because I need a session to be able to use passport-azure-ad with oidc strategy.

I was having some issues logging in with Microsoft accounts after some time and came to the conclusion that it is because the session cookie (connect.sid) is never cleared from the browser.

I had some things misconfigured and made some changes but even with all the changes it is still not working.

Session on my Express app is configured in the following way:

import session from 'express-session';
import expressSequelizeSession from 'express-sequelize-session';

const Store = expressSequelizeSession(session.Store);

app.use(session({
  cookie: {
    path: '/',
    httpOnly: true,
    secure: env !== 'development', // On environments that have SSL enable this should be set to true.
    maxAge: null,
    sameSite: false, // Needs to be false otherwise Microsoft auth doesn't work.
  },
  secret: config.secrets.session,
  saveUninitialized: false,
  resave: false,
  unset: 'destroy',
  store: new Store(sqldb.sequelize),
}));

On the FE I'm using Vue.js with Axios and setting withCredentials to true so that the cookie is passed on the HTTP request.

// Base configuration.
import Axios from 'axios';

Axios.defaults.baseURL = config.apiURL;
Axios.defaults.headers.common.Accept = 'application/json';
Vue.$http = Axios;

// When making request.
Vue.$http[action](url, payload, { withCredentials: true }).then(() => // Handle request);

You can see from the image that the cookie is being sent on the logout request.

enter image description here

When logging out I'm hitting this endpoint and destroying the session as is explained on the documentation.

router.post('/logout', (req, res) => {
  try {
    req.session.destroy(() => {
      return responses.responseWithResultAsync(res); // Helper method that logs and returns status code 200.
    });

    return responses.handleErrorAsync(res); // Helper method that logs and returns status code 500.
  } catch (error) {
    return responses.handleErrorAsync(res, error); // Helper method that logs and returns status code 500.
  }
});

The interesting thing is that the session on the DB is removed so I know that the cookie is being sent properly on the request with the right session ID but it is not removing it on the browser for some reason. After logging out I still have this:

enter image description here

Does anyone know what I'm doing wrong? I find it odd that the session is being removed on the DB successfully but not on the request.


Solution

  • As @RolandStarke mentioned the express-session library doesn't have the built in functionality to remove the cookie from the browser, so I just did it manually in the following way:

    router.post('/logout', (req, res) => {
      try {
        if (req.session && req.session.cookie) {
          res.cookie('connect.sid', null, {
            expires: new Date('Thu, 01 Jan 1970 00:00:00 UTC'),
            httpOnly: true,
          });
    
          req.session.destroy((error) => {
            if (error) {
              return responses.handleErrorAsync(res, error);
            }
    
            return responses.responseWithResultAsync(res);
          });
        }
    
        return responses.responseWithResultAsync(res);
      } catch (error) {
        return responses.handleErrorAsync(res, error);
      }
    });