Question

I have a Chicken and Egg problem.

I am using a Node.js HTTPServer to route web requests to different Node.js workers, depending on their Connect.SID cookie that is sent in the request headers.

Each of my Node.js workers use Connect / Express and assign Connect.SID cookies when a request connects for the first time.

Problem

Apparently, if the request has a Connect.SID that is not registered with that instance of Node, Connect assigns a new ID.

So, I have a new Connect.SID. My HTTP Proxy logs ID 12345 and routes it to worker #5. Worker #5 sends back new ID 56344 to the browser. Next browser request - HTTP Proxy sees a brand new ID - 56344 - logs it and sends to Worker #6. Worker #6 sees new SID and....

The Connect Session middleware is too... simple...

app.use(express.cookieParser());
app.use(express.session({ secret: "niceTry", cookie: { /* ... */ } }));

Is there a way to inject logic into its assignment of a new Session ID so it skips it if there is already an unregistered, but valid, Connect.SID?

Was it helpful?

Solution 2

I managed to modify Connect's source code to get this working, as below. However, I am still looking for a way to move these modifications out of Connect, so I don't have to mess around with a fork of it.

node_modules\connect\lib\middleware\session.js - append after line 312:

if (!sess) {
  store.sessions[req.sessionID] = JSON.stringify({
    "cookie": {
      "originalMaxAge": void 0,
      "expires": void 0,
      "httpOnly": void 0,
      "path": void 0,
      "passport": void 0,
    }
  });
  next();
  return;
} 

By default, Connect creates a new session if the given SID is not in its store. This bypasses that, inserting it manually into the store.

How does one port this out of Connect.js to some middle-ware, perhaps, right above:

app.use(express.cookieParser());
app.use(express.session({ secret: "niceTry", cookie: { /* ... */ } }));

UPDATE

Okay I finally figured it out:

I added middleware to my main server.js file, and this handles the problem without modifying connect's source code.

var MemoryStore = require('connect/lib/middleware/session/memory');
app.store = new MemoryStore();

app.use(express.cookieParser());

app.use(function(req, res, next){

  var cookie = req.signedCookies['connect.sid'];
  if (!cookie && req.cookies['connect.sid']) {
    cookie = connect.utils.parseSignedCookie(req.cookies['connect.sid'], app.cookieSecret);
  }

  app.store.get(cookie, function(err, sess){
    if (!sess) {
      app.store.sessions[cookie] = JSON.stringify({
        "cookie": {
          "originalMaxAge": void 0,
          "expires": void 0,
          "httpOnly": void 0,
          "path": void 0,
          "passport": void 0,
        }
      });
      next();
    } else {
      next();
    }
  });
});

app.use(express.session({ store: app.store, secret: app.cookieSecret, cookie: { httpOnly: false, maxAge: null } }));

OTHER TIPS

Have you considered using distributed session management (i.e. Redis) with Node/Express? That should prevent what is effectively a session pinning issue.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top