37

I need help understanding the concept of sessions for a web application. I am running a Node.js server with Express 3.0.

My goals are to:

  • Create a session for each user that logs in

  • Store this session and use it for validating if the user is already logged in (prevent two devices using the same user at the same time) and to limit access to certain pages (by matching session ID to some other data)

I will be using MemoryStore to save the sessions (seems easiest). If the above goals make sense can you provide a thorough explanation of how to achieve them?

Community
  • 1
  • 1
  • 1
    You should take a look at [Passport](http://passportjs.org/) – mekwall Jan 08 '13 at 15:47
  • 4
    I already tried using passport and could not get it to work properly, I thought that using the default sessions in express would be easier. –  Jan 08 '13 at 15:55
  • 1
    You might want to read this: http://stackoverflow.com/questions/11187342/mongoose-express-authorisation-on-http-verbs Session is nothing else then an entry in db/memory with a unique id. – freakish Jan 08 '13 at 16:03
  • Here's a pretty detailed description of how sessions work in express. http://stackoverflow.com/a/11585839/74291 – Waylon Flinn Jul 28 '13 at 16:42

2 Answers2

41

Express has nice examples in the github repo. One of them deals with authentication and shows how to attach the user to the req.session object. This is done inside the app.post('/login') route.

To limit access to certain pages add a simple middleware to those routes

function restrict(req, res, next) {
  if (req.session.user) {
    next();
  } else {
    req.session.error = 'Access denied!';
    res.redirect('/login');
  }
}

app.get('/restricted', restrict, function(req, res){
  res.send('Wahoo! restricted area, click to <a href="/logout">logout</a>');
});

As Brandon already mentioned you shouldn't use the MemoryStore in production. Redis is a good alternative. Use connect-redis to access the db. An example config looks like this

var RedisStore = require('connect-redis')(express);

// add this to your app.configure
app.use(express.session({
  secret: "kqsdjfmlksdhfhzirzeoibrzecrbzuzefcuercazeafxzeokwdfzeijfxcerig",
  store: new RedisStore({ host: 'localhost', port: 3000, client: redis })
}));
Community
  • 1
  • 1
zemirco
  • 16,171
  • 8
  • 62
  • 96
10

Use MemoryStore in express ONLY if you are not creating multiple instances (such as with the cluster module). If you are load balancing across machines, your load balancer will need to use sticky / persistent sessions.

If you meet those requirements, then all you need to do is upon login, once the credentials are validated, set a session variable to indicate logged in, for example:

req.session.loggedIn = true;

If you want to check if a user is logged in, simply check that variable.

if (req.session.loggedIn) {
    // user is logged in.
}
else {
    // user is not logged in.
}

You mentioned preventing a single user from having sessions more than one session at a time. To achieve that, you may need to store something in a database indicating that the user is logged in. I warn you, this can be dangerous because of stale sessions. For example, what if a user logs in, but never logs out? What if they close their browser window so the session is gone forever?

Express has no concept of an idle session expiration. I have implemented such a thing by storing all sessions in the database along with a last accessed timestamp and then periodically clean up the session data based on the time. But then you need to update your list of who is logged in as well.

Brandon
  • 9,822
  • 3
  • 27
  • 37
  • He could override the last session, disabling the old one this way and preventing 'stale sessions' to be a problem? – Neikos Sep 12 '13 at 03:06
  • Not sure why he'd need to use sticky ports over round robin? Using round robin with connect_redis will allow sessions to work on any instance of the web site. Plus the author claims it's [insanely fast](https://github.com/visionmedia/connect-redis), but what you possibly lose in performance you gain in fault tolerance. – Eat at Joes Aug 12 '14 at 17:45
  • @Neikos : I need t implement exactly that mechanism but having a hard time getting around it. You have any suggestions? Please answer here : http://stackoverflow.com/questions/29144827/express-js-passport-js-how-to-restrict-multiple-login-by-the-same-user – vivekanon Mar 19 '15 at 13:37