node.js + express.js: session handling with mongodb/mongoose

41,179

Solution 1

in the end i'm using a bit of every answer that was given before:

  • i switched from connect-mongodb to connect-mongo module
  • i'm using a general conf object to store my configuration data
  • there are two db connections because it's easier to handle for me (maybe changed later on, if/when a new version of mongoose/express comes out)

requirements:

var express = require('express'),
    MongoStore = require('connect-mongo')(express),
    mongo = require('mongoose');

conf object:

var conf = {
  db: {
    db: 'myDb',
    host: '192.168.1.111',
    port: 6646,  // optional, default: 27017
    username: 'admin', // optional
    password: 'secret', // optional
    collection: 'mySessions' // optional, default: sessions
  },
  secret: '076ee61d63aa10a125ea872411e433b9'
};

then i can configure it like this:

app.configure(function(){
  // ...
  app.use(express.cookieParser());
  app.use(express.session({
    secret: conf.secret,
    maxAge: new Date(Date.now() + 3600000),
    store: new MongoStore(conf.db)
  }));
  // important that this comes after session management
  app.use(app.router);
  // ...
});

and finally connect to mongodb a second time using mongoose:

var dbUrl = 'mongodb://';
dbUrl += conf.db.username + ':' + conf.db.password + '@';
dbUrl += conf.db.host + ':' + conf.db.port;
dbUrl += '/' + conf.db.db;
mongo.connect(dbUrl);
mongo.connection.on('open', function () {
  app.listen(3000);
});

Solution 2

Please include

app.use(express.cookieParser());

directly before

app.use(express.session({

Otherwise throws error as below,

TypeError: Cannot read property 'connect.sid' of undefined

Solution 3

It looks like you could do this to setup connect-mongodb assuming your mongoose connection code above is run earlier:

app.use(express.session({
  secret: 'topsecret',
  maxAge: new Date(Date.now() + 3600000),
  store: new mongoStore({ db: mongoose.connections[0].db })
}));

Solution 4

So connect-mongodb does not use Mongoose, it uses the node-mongodb-native driver (i.e.: npm install mongodb). Mongoose also depends on this driver, so it should be present.

Looking at the code directly, you have to provide your DB connection information as a MongoStore object:

store: new mongoStore({ host: 'session_server', port: 27017, db: 'seesion', collection: 'sessions' })

Typically for this, you'll want to have some "config" object or variable that can be dynamically loaded (dev vs test vs prod). Then you pull the host/port/db/auth off of that config object.

Solution 5

For express 4x:

var express = require('express'),
    session = require('express-session'),
    MongoStore = require('connect-mongo')(session),
    mongo = require('mongoose');

var conf = {
  db: {
    db: 'myDb',
    host: '192.168.1.111',
    port: 6646,  // optional, default: 27017
    username: 'admin', // optional
    password: 'secret', // optional
    collection: 'mySessions' // optional, default: sessions
  },
  secret: '076ee61d63aa10a125ea872411e433b9'
};

app.configure(function(){
  app.use(express.cookieParser());
  app.use(session({
    secret: conf.secret,
    maxAge: new Date(Date.now() + 3600000),
    store: new MongoStore(conf.db)
  }));
});

var dbUrl = 'mongodb://';
dbUrl += conf.db.username + ':' + conf.db.password + '@';
dbUrl += conf.db.host + ':' + conf.db.port;
dbUrl += '/' + conf.db.db;
mongo.connect(dbUrl);
mongo.connection.on('open', function () {
  app.listen(3000);
});

session has been moved to it's own module, so you need to require it and use session when configuring the MongoStore.

Share:
41,179
Philipp Kyeck
Author by

Philipp Kyeck

.

Updated on July 05, 2020

Comments

  • Philipp Kyeck
    Philipp Kyeck almost 4 years

    Right now i'm storing my session data in the "memory store" which comes bundled with connect(express). But I want/have to change this for production.

    The application is using mongodb and I installed mongoose to handle all db-communications.

    e.g. Connect to the DB after initializing my app:

    var mongo = require('mongoose');
    mongo.connect('mongodb://localhost/myDb');
    mongo.connection.on('open', function () {
      app.listen(3000);
    }
    

    I found the connect-mongodb module, but I don't know how to implement it using mongoose, or if it's actually possible? I need to add something like this:

    var mongoStore = require('connect-mongodb');
    // ...
    app.use(express.session({
      secret: 'topsecret',
      maxAge: new Date(Date.now() + 3600000),
      store: new mongoStore({ db: 'myDb' })
    }));
    

    or do I have to define my db connection a second time using the mongodb-module directly?

  • Philipp Kyeck
    Philipp Kyeck almost 13 years
    you link to connect-mongo, i used connect-mongodb in the example. but they're almost identical, so i will check this out.
  • Philipp Kyeck
    Philipp Kyeck almost 13 years
    i'm using the express.session() in app.configure() before i connect to the DB. i think, i'll define a config object which contains all DB info and try to use connect-mongo (instead of connect-mongodb) - implementation looks easier than connect-mongodb
  • Salida Software
    Salida Software over 12 years
    Good work! Only addition I have that was compounding my troubles is to make sure that your "app.use(app.router);" is placed after the "app.use(express.session...".
  • Peter Downs
    Peter Downs almost 12 years
    For anyone trying to get this working recently: it seems that as of v0.1.9, you'll need to set express as a varilable (var express = require('express')) and then pass that to connect-mongo (var MongoStore = require('connect-mongo')(express)). This works because express exposes all of the underlying parts of connect, and connect-mongo is actually a function that takes the connect object as an argument.
  • antitoxic
    antitoxic over 11 years
    That saves lives. The internet is wrong on this - there wasn't a single example from the top of the results even suggesting about this.
  • Joscha
    Joscha over 11 years
    Thank you so much - that fixed it!
  • CommaToast
    CommaToast over 11 years
    In order to avoid EADDRINUSE errors I had to remove the "app.listen(3000)" line from the bottom section of code that you had, because I was already doing my .listen somewhere else. That part only needs to be done once and is for starting the actual express webserver itself -- not relevant per se to the mongodb connection. Just a note!
  • Philipp Kyeck
    Philipp Kyeck over 11 years
    thanks for the hint but next time, just edit my answer and add the missing line so that others won't have to read another answer ...
  • Hadesara
    Hadesara about 11 years
    Okay, I reached till here, but now how do I interact with the session? set and get values..
  • ngChris
    ngChris almost 10 years
    @Hadesara There is excellent documentation on expressjs and sessions here: expressjs-book.com/forums/topic/…
  • mauris
    mauris over 9 years
    the example in the github page doesn't tell how to use with mongoose. this example helped a lot.
  • Kawd
    Kawd over 8 years
    Hi there, I'm trying to understand express-session myself and I've run into an issue when ti comes to storing sessions in mongoDB - Do you think you could take a look here : stackoverflow.com/questions/32413051/… ? Thanks!
  • David
    David almost 8 years
    From repo mongoose-session, INACTIVE. Use connect-mongo instead. It's better anyways.
  • User007
    User007 over 7 years
    In line 3, what exactly it means by (session) after require statement. Is it like (session) is passed to mongoStore