Express session with different cookie domain per request?
Asked Answered
A

1

15

I have a situation where an app can be accessed from multiple different domains. For instance, foo.com and bar.com could both in theory point to my app. Additionally, their subdomains can also point to my app, so for instance red.foo.com and blue.foo.com. I'm using Express cookie sessions, and my initialization code for the session looks like that:

app.use(express.session({
    secret: "secret",
    cookie: {
        domain: ".foo.com"
    },
    store: new MongoStore({
        db: db
    })
}));

That works well for when users go through foo.com or any of it's subdomains, but bar.com won't work. I need to have both at once. Ideally, I would set it to a different domain per request, but I'm not sure how I would do that. My requests are highly asynchronous and if I just set it for the whole app at every request, I fear it might not work when two calls come in at once.

Is this at all possible? Does anyone have any ideas to solve this?

Aboard answered 30/9, 2013 at 21:36 Comment(2)
@fardjad this would be ideal, would you have any more information? I am not as familiar as I wish I was with middlewaresAboard
So essentially, I would loop through the list of domains that I want to be able to set sessions on, and do an app.use for each one? So there would be a bunch of different express.session middleware initialized at the beginning of my app, and active throughout the life of my app?Aboard
Q
22

Here's what you do:

  • write a middleware your app can use in place of the default express.session middleware
  • in that middleware, based on the host request header instatiate and configure on instance of the express session middleware per domain, and then actually execute the middleware function appropriate for this request

pseudocode

var mwCache = Object.create(null);
function virtualHostSession(req, res, next) {
  var host = req.get('host'); //maybe normalize with toLowerCase etc
  var hostSession = mwCache[host];
  if (!hostSession) {
    hostSession = mwCache[host] = express.session(..config for this host...);
  }
  hostSession(req, res, next);
  //don't need to call next since hostSession will do it for you
}

app.use(virtualHostSession);

My requests are highly asynchronous and if I just set it for the whole app at every request, I fear it might not work when two calls come in at once.

Absolutely you cannot do that. It will be utterly incorrect.

Quinte answered 30/9, 2013 at 22:30 Comment(5)
HTTP forbids domain X server setting a cookie for domain Y. I believe my approach above solves the user's problem as described, however it's not going to carry over a single session ID for one browser visiting multiple host names, but it is going to allow a single app to function on multiple host names.Quinte
Yeah if you want to start sharing info across domains, look no further than the awesome world of online advertising tracking for an arsenal of invasive techniques such as tracking pixels, etc.Quinte
Holy hell thank you so much. I've just finished implementing it and I can finally go home. Works like a charm. You have no idea how relieved I am to have figured this out. Because of a series of events, this was happening on a live server and it needed to be fixed fast. Thank you.Aboard
@AlexTurpin By any chance you have shared the middleware ?Dixil
Awesome! In case anybody else is using this excellent answer and gets burned by the same thing I just did: if you use this, you may need to create a separate session store object per middleware. Otherwise, the cookie settings you set on one middleware might leak to another one through the store.Marlonmarlow

© 2022 - 2024 — McMap. All rights reserved.