7

Is there a way to control when a session starts with connect's session middleware?

For example, if I have express app config:

var app = express();
app.configure(function(){
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser('secret'));
  app.use(express.session({ store:sessionStore, ... }));
});

Then on every request, if no session cookie is given, a session is started. What if I wanted to start a session only when the user has been authenticated?

For example, say I have two routes /protected and /login.

  • If someone hits /protected without a session cookie, the middleware will NOT start a new session. (req.session is null)
  • If someone hits /protected with a session cookie, the middleware will CHECK to see if there is a matching active session for the cookie and set req.session, but will not start a new session. (req.session could have a value or be null)
  • If someone hits /login with the correct params, then a session is started explicitly and a cookie is set only then.

The only way to start a session should be explicitly:

app.post('/login', function(req, res, next) {
  // connect to database and validate user...
  db.authenticate( req.body.user, req.body.pass, function(allow) {
    if (allow) {
      // START SESSION HERE
      // this will send set the cookie
    }
  });
}

Is there any way of accomplishing this with the existing connect session middleware?

Chenmunka
  • 685
  • 4
  • 21
  • 25
ralouphie
  • 116
  • 3

2 Answers2

2

What you want to do is to remove this line:

app.use(express.session({ store:sessionStore, ... }))

Now sessions are disabled by default and it's up to you to decide which controller is going to use them:

var useSessions = express.session({ store:sessionStore, ... });

var preCb = function (req, res, next) {
  // authenticate and stuff
  // ....
  if (authenticated === true) {
     next();
  }
};

app.post('/login', useSessions, function(req, res, next) { ... });
app.post('/protected', preCb, useSessions, function(req, res, next) { ... });
kyokpae
  • 121
  • 4
0

Even if a session is started every time, it does not really matter because it will be empty. If you are attempting to use it to authenticate access (which seems to be the case), the simplest solution is to set an attribute in your session (such as req.session.authenticated = true;), and check that. This way technically ever visitor has a session, however you will only utilize the session if req.session.authenticated == true. It may not be exactly what you're looking for, but it is the easiest way to get this done.

Nick Mitchinson
  • 5,452
  • 1
  • 25
  • 31
  • 1
    If you're using a backing database session store, then *every* anonymous user will be creating sessions that are stored in the database. – ralouphie Jan 18 '13 at 01:17
  • I do understand that, however you should not be keeping session data forever anyways. When session data expires it should be removed, and if an anonymous user only visits a few pages on your site, it should be removed rather quickly after they leave. As well, the sessions for the anonymous users will essentially be empty objects (correct me if I'm wrong) and thus should not be a huge memory burden. – Nick Mitchinson Jan 18 '13 at 01:21
  • The way the session middleware works, it will create a session for every user without one (without the cookie). This means that the database will have an entry for every request which doesn't send a cookie. In the system I am working on this is unacceptable. – ralouphie Jan 18 '13 at 01:24
  • If you are storing your session information in a database and not clearing expired information I can see how this would be a problem. What you could try (I'm not sure if this will work) would be to create your own piece of middleware which checks for the session cookie. If it exists, then you app.use(express.session(..)), otherwise just call next(). I am not quite sure if this would work, but it is just a thought. Take a look here for creating middleware: http://www.hacksparrow.com/how-to-write-midddleware-for-connect-express-js.html – Nick Mitchinson Jan 18 '13 at 01:35
  • Yea, I think I'll just implement my own middleware to handle it. This seems like a lacking feature in my opinion. – ralouphie Jan 18 '13 at 02:22