session icon indicating copy to clipboard operation
session copied to clipboard

Can't set manual sessionID

Open JasperH8g opened this issue 10 years ago • 17 comments
trafficstars

Similar to #148, I'm can't seem to set a manual sessionID. Setting it in signedCookies like seems to be the solution doesn't seem to work:

app
  .use(function(req, res, next) {
    if(req.query.sessionID) {
      req.signedCookies["connect.sid"] = req.query.sessionID;
    }
    next();
  })
  .use(session({
    httpOnly: false,
    secret: 'secret',
    resave: false,
    saveUninitialized: true
  })
  .get('/session', function(req, res) {
    console.log('sessionID:', req.sessionID);
    req.session.tmp = req.session.tmp + 1 || 0;
    req.session.save();
    res.send('session: ' + req.session.tmp);
  })

When I hit http://localhost:3000/session?sessionID=42 a couple of times, the counter goes up. When I hit that exact same url in a different browser I expect it to pick up the count from the session, but it does not.

An observation: The log for req.sessionID is not what I gave to the query string, so I guess it's initialising its own sessionID instead.

I've also tried a custom genid like so:

  .use(session({
    httpOnly: false,
    secret: 'secret42',
    resave: false,
    saveUninitialized: true,
    genid: function(req) {
     return req.query.sessionID || uuid.v1();
   }
  })

This seemed like a cleaner solution anyway, but it also doesn't work for me. It sets the sessionID correctly for the first hit, but it won't update it for requests with a different sessionID.

Any help on this would be great!

JasperH8g avatar May 16 '15 19:05 JasperH8g

Yes, that work around only works for non-browsers, which do not carry cookies. For this to work in web browsers, you'll need to do a lot of work, sadly, to sign that unsigned value, then form a fake cookie header from it, place it in the right req.headers spot, and remove the incoming value. Otherwise, this module needs to be modified to allow an alternative method besides cookies.

The old express 3 didn't allow for an alternative, either, but it was easier to trick that module (or older versions of this module, which was a copy and paste of express 3).

dougwilson avatar May 16 '15 19:05 dougwilson

Another workaround could be using the solution from that other issue and also just delete all incoming cookies (if that is an option) by adding "delete req.headers.cookie".

dougwilson avatar May 16 '15 19:05 dougwilson

Thats too bad.. Deleting req.headers.cookie results in no working sessions at all. Can you point me in the right direction on how to implement the other solution?

JasperH8g avatar May 16 '15 20:05 JasperH8g

Deleting req.headers.cookie results in no working sessions at all

Really? It should work, when combined with the workaround of setting req.signedCookies you have above (i.e. do the delete when you set req.signedCookies).

As for the fuller solution, I can see about trying to write it up when I get back to a computer, but really, a PR to allow non-cookie-based sessions would be better in the long run.

dougwilson avatar May 16 '15 20:05 dougwilson

Essentially we don't officially support non-cookie-based sessions until there is a PR offered up that works well and is accepted.

dougwilson avatar May 16 '15 20:05 dougwilson

To avoid any mixups, this is what i've tried:

app
  .use(function(req, res, next) {
    if(req.query.sessionID) {
      req.signedCookies["connect.sid"] = req.query.sessionID;
      delete req.headers.cookie;
    }
    next();
  })
  .use(session({
    httpOnly: false,
    secret: 'secret',
    resave: false,
    saveUninitialized: true
  })
  .get('/session', function(req, res) {
    console.log('sessionID:', req.sessionID);
    req.session.tmp = req.session.tmp + 1 || 0;
    req.session.save();
    res.send('session: ' + req.session.tmp);
  })

I agree that a non-cookie-option in the module would be a better solution. I'll investigate what needs to be done in the next couple days.

JasperH8g avatar May 16 '15 20:05 JasperH8g

This option turned out to be pretty easy to implement, but I don't have a huge amount of experience in express-middlewares. Can you take a look and see if it makes any sense?

https://github.com/expressjs/session/compare/cda52fcdac4c84f6c54d161e0380fe5fbb9b93ae...Jpunt:master

If so, I'll make some tests and a PR :)

JasperH8g avatar May 17 '15 16:05 JasperH8g

Just go ahead and make the PR right away :) I can comment on it and we can always iterate!

dougwilson avatar May 17 '15 16:05 dougwilson

Alright! :metal:

JasperH8g avatar May 17 '15 16:05 JasperH8g

This was a real life saver. Can this be merged onto master ?

weepy avatar Jul 26 '16 08:07 weepy

Agreed. When can we expect this to be merged into master?

jacoscaz avatar Aug 07 '16 15:08 jacoscaz

really need to set the manual sessionID

mgttt avatar Apr 12 '18 03:04 mgttt

emergency emergence emerge merger merger ... merge

knoxcard avatar Jun 04 '18 07:06 knoxcard

Middleware configuration:

const uid = require("uid-safe").sync;

var middleware = session({
  genid: function(req) {
    if ( (req.session) && (req.session.uid) ) {
      return req.session.uid + "_" + uid(24);
    } else {
      return uid(24);
    }
  }
  secret: config.cookieSecret,
  store: sessionStore,
  resave: false,
  saveUninitialized: false
})

On successfull authentification:

req.session.uid = data.id;
req.session.regenerate(function (err) {
  if (err) throw err;
  req.session.uid = data.id;
  // ...
});

em92 avatar Jun 04 '18 07:06 em92

@em92 - Clever... Thanks!

knoxcard avatar Jun 04 '18 08:06 knoxcard

Simply remove cookie/headers by creating a middleware for route, and run before session middleware -> this help express-session alway run to genid function

function makeid(length) {
  var result           = '';
  var characters       = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  var charactersLength = characters.length;
  for ( var i = 0; i < length; i++ ) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
}
  let app = express();
  app.use('/test', (req, res, next) => {
    console.log("Delete cookie, header values:", req.headers);
    delete req.cookies;
    delete req.headers['cookie'];
    next();
  })
  app.use(session({
    genid: function(req) {
      console.log('Run to genid function', req.query);
      if (req.query.ssId) {
        return req.query.ssId;
      } else {
        return makeid(12);
      }
    },
    resave: false,
    saveUninitialized: false
  }));

  const router = express.Router()

  router.use('/test', (req, res, next) => {
    req.session.user_data={name: "cuong ta"};
    res.json({
      receive: true,
      sessionId: req.sessionID
    });
  })

Test with http://localhost/test?ssId=123456

cuongtavan avatar Oct 08 '19 10:10 cuongtavan

Need this too: I.e. allow to customise the way a request is associated with its session, as opposed to hard coded dependency on sid-cookie.

@em92 genid does not appear to be a solution. In will not re-associate the req with an existing session. The SID changes but the existing session data is lost in my testing.

sgpinkus avatar Apr 04 '20 06:04 sgpinkus