Using cookieParser() and cookieSession() together?

cookieParser() gives us the option of signing cookies with a secret sentence, which is great to prevent tampering. I understand that a cookie is signed with a special value, to prevent tampering.

I just discovered cookieSession(), which I find to be a great alternative to server-stored cookies (I only store { loggedIn = true, userId=763487246824632}, it never grows).

But... I found that setting a "secret" for cookieParser() breaks things, and cookieSession() stops working if the secret sentence matches. The reason seems to be that if the cookie is signed using the same secret, then cookieParser() actually takes it and parses it. The strange thing is that once cookieParser() has done its work, and with the same signature secret, the session is set to:

{ cookie: 
   { path: '/',
     _expires: null,
     originalMaxAge: null,
     httpOnly: true } }

Rather than:

{ testing: 'OOO' }

(Each reload adds an 'o') So...

  • Did my analysis get it right?
  • Do you know why the session is set to that strange { cookie object if the secret sentences match?

Merc.

Your analysis is correct, I can reproduce it.

The issue is caused by this line in the cookieSession middleware (some context: options.secret is the key passed to cookieSession, req.secret is the key passed to cookieParser): if you pass both middleware a secret key, cookieSession assumes that it will find the raw (unparsed) cookie in req.cookies.

But since cookieParser has picked up the signed cookie as well (and it's being run before cookieSession), it has parsed the cookie itself (and because the signing keys were the same, it succeeded to do so), stored it in req.signedCookies and deleted it from req.cookies. So as far as cookieSession is concerned, the cookie just isn't set.

The object you see is the default session contents (which is the cookie property from the cookieSession configuration):

app.use(express.cookieSession({
  cookie : { // <-- this object
    ...
  }
});

As for a solution: either use a different key for each middleware, or just pass one of them your secret key, but not both (with the understanding that if you pass it to cookieParser, all your cookies will be signed).

FWIW: I'm not entirely sure if this is a real bug. It's a consequence of using the same signing mechanism for both cookieParser and cookieSession, with no distinction between cookies signed by one or the other. Although it could be fixed by always checking if the cookie is located in req.signedCookies.