Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sessions with express.js + passport.js

Goal

What I want to do:

  • Create a session for the user
  • Create a session for the socket (socket.io)
  • Use passport.js to authenticate the login and socket sessions.

Notes

I have installed MongoStore and passport.socket.io npm's. I can login and set the cookie of the user logged in (connect.sid)


QUESTION

How do I setup the system to store socket sessions and couple them with the session of the user?


Code

app.js

  /* The usual express setup */
  passport = require('passport'),
  LocalStrategy = require('passport-local').Strategy,
  User = require('./models/user.js'),
  MongoStore = require('connect-mongo')(express);

app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.session({
    secret: 'chuck norris', 
    store: new MongoStore({db: User.name}, // the db's name
        function(err) {
          console.log(err || 'connect ok!');
        })
  }));
  app.use(express.methodOverride());
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);

app.js (the passport part)

passport.use(new LocalStrategy({
    usernameField: 'username',
    passwordField: 'password'
  },
  function(username, password, done) {
    User.findOne({username: username}, function(err, user) {
      if(!user) {
        return done(null, false, {message: 'Incorrect Username!'});
      }
      if(!user.validPassword(password)) {
        return done(null, false, {message: 'Incorrect Password!'});
      }
      return done(null, user);
    });
  }
));


passport.serializeUser(function(user, done) {
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user);
  });
});

app.post('/',
  passport.authenticate('local'),
    function(req, res) {
      res.redirect('/home/'+req.user.username);
    });

app.js (socket.io part)

io.set('authorization', passportSocket.authorize({
  key: 'connect.sid',
  secret: 'chuck norris',
  store: /* Not entirely sure what goes here */
  fail : function(data, accept) { accept(null, false); },
  success: function(data, accept) { accept(null, true); }
}));


io.sockets.on('connection', function(socket) {
  console.log('User Connected: ' + socket.handshake.user.username);
});
like image 806
ashley Avatar asked Feb 26 '13 15:02

ashley


1 Answers

You store your new memory story object instance into a variable and pass it in to both express and socket io like so. (be aware that we are using different stores but in theory it should not matter what store you use as long as you pass off control the proper way)...

var ...
,MemoryStore = express.session.MemoryStore
,sessionStore = new MemoryStore();

then in app.configure you...

app.use(express.session({store:sessionStore,secret:'secret',key:'express.sid'}));

and finally in socket.io configure

io.configure(function (){
io.set("authorization", passportSocketIo.authorize({
    key:    'express.sid',       //the cookie where express (or connect) stores its session id.
    secret: 'secret', //the session secret to parse the cookie
    store:   sessionStore,     //the session store that express uses
    fail: function(data, accept) {
        // console.log("failed");
        // console.log(data);// *optional* callbacks on success or fail
        accept(null, false);             // second param takes boolean on whether or not to allow handshake
    },
    success: function(data, accept) {
      //  console.log("success socket.io auth");
     //   console.log(data);
        accept(null, true);
    }
}));

If you have done this correctly and your user successfully authenticates you should then be able to access the session data on the handshake object.

console.log(socket.handshake.user.username);
//or sometimes it might be...
console.log(socket.handshake.user[0].username);

Hope that helps.

like image 175
Ray Garner Avatar answered Oct 26 '22 06:10

Ray Garner