Node JS, express-session, remove cookie from client browser

Viewed 5694

I work with app, that already has its own infrastructure. The task is to prevent user login in several browser. Our application has single app architecture, so ideally user should work only in one browser tab. And I have a problem. I can’t remove cookie from client.

I. Briefly.

App settings:

Server: NodeJS Port: 8083

Client: VueJS Port: 8088

I use module express-session to initialize session mechanism on server side and send cookies to client. Client hasn’t set cookies.

II. Details:

Server’s root file is index.js

I do the following in it:

  1. Plug in express module:
const express = require('express')
  1. Plug in cors module:
const cors = require('cors')
  1. Add cors settings:
app.use(cors({
    origin: 'http://localhost:8088',
    credentials: true
}))

Then I initialize session in user.js file and receive client’s connects:

  1. Plug in express-session module:
const session = require('express-session')
  1. Plug in routing by express.Router():
const router = express.Router()
  1. Add session settings:
const EIGHT_HOURS  = 1000 * 60 * 60 * 8
const {
    SESS_NAME = 'sid',
    SESS_LIFETIME = EIGHT_HOURS,
    SESS_SECRET = 'test',
    NODE_ENV = 'development'
} = process.env
const IN_PROD = NODE_ENV === 'production'
  1. Initialize session:
router.use(session({
    name: SESS_NAME,
    resave: false,
    saveUninitialized: false,
    secret: SESS_SECRET,
    cookie: {
        maxAge: SESS_LIFETIME,
        sameSite: false,
        // Must have HTTPS to work 'secret:true'
        secure: IN_PROD
    }
}))
  1. Receive client queries by router.post()

So what I did:

  1. I use req.session.destroy to remove session data and expect the browser logout user from certain browser and cookies clear.
req.session.destroy(err => {
            if (err) {
                return res.send({ error: 'Logout error' })
            }
            res.clearCookie(SESS_NAME, {path: '/'})
            return res.send({ 'clearSession': 'success' })
        })

Unfortunately nothing magic happens

  1. I read different topics. For example, here (GitHub) offer the conclusion: use explicit cookie’s path indication in res.clearCookie method as shown above. That didn’t work.

  2. Wrote this setting {path: '/'} in cookies settings. Didn’t work too.

router.use(session({
    name: SESS_NAME,
    resave: false,
    saveUninitialized: false,
    secret: SESS_SECRET,
    cookie: {
    path: '/',
        maxAge: SESS_LIFETIME,
        sameSite: false,
        // Must have HTTPS to work 'secret:true'
        secure: IN_PROD
    }
}))

And as wrote in express-session documentation (NPM:express-session) this path is the default path for cookie storage.

  1. Add req.session = null in req.session.destroy:
req.session.destroy(err => {
            if (err) {
                return res.send({ error: 'Logout error' })
            }
            req.session = null
            res.clearCookie(SESS_NAME, {path: '/'})
            return res.send({ 'clearSession': 'success' })
        })

That didn’t work

  1. delete req.session doesn’t work too.

So, how can I resolve this problem? What should I do?

5 Answers

adding .send('cleared cookie') made my browser clear its cache of the named cookie.

const logOutRequest = (req, res) => {
      req.session.destroy((err) => {
         res.clearCookie("notcookie").send('cleared cookie');
      });
    };

Have you tried removing the exact cookie by setting it to null that is lets say that you are dealing with a cookie named Views you could remove the cookie using req.session.Views = null

Instead of doing this

req.session.destroy(err => {
            if (err) {
                return res.send({ error: 'Logout error' })
            }
            req.session = null
            res.clearCookie(SESS_NAME, {path: '/'})
            return res.send({ 'clearSession': 'success' })
        })

you could do the name of your session cookie and set that to null that is

req.session.sid= null

This removes the cookie from client browser

req.session.destroy(err => {
    res.clearCookie("session-cookie-name", { path: "/" });
  });

The most important key is setting 'domain' in the clearCookie method to solve your issue. Expressjs will return the following in the http response header. However, it seems that on the browser or some browsers that I tested, it doesn't know which cookie belonging to which domain to clear, hence, the cookie remains there. You do not need to include the path when calling clearCookie

Set-Cookie: mycookie=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT

You have to set domain like below:

 req.session.destroy(err => {
        res.clearCookie("session-cookie-name", { domain: 'your-domain' });
    });

Then response header will become

Set-Cookie: mycookie=; Domain=your-domain; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT

The browser will clear the cookie nicely!

this works for me

@Post('signout')
async signout(@Req() req: Request, @Res({ passthrough: true }) res: Response) {
  const user = req.user

  if (!user) return {}

  await new Promise<void>((resolve, reject) => {
    req.session.destroy((err) => {
      if (err) {
        reject(err)
      } else {
        res.clearCookie('ACCESS_TOKEN', {
          domain: '.xxx.com'
        })
        res.clearCookie('REFRESH_TOKEN', {
          domain: '.xxx.com'
        })
        res.clearCookie('connect.sid', {
          domain: '.xxx.com'
        })

        resolve()
      }
    })
  })

  return {}
}
Related