Best practice building login for Node.js using socket.io and express

628 views Asked by At

I built an app with node.js server using express 4.12.4 and socket.io. Now I have some socket-events that should be restricted only to the admin user. Since there are tons of plugins and possibilities I'm little confused. Unfortunately all the examples I found where outdated. So if somebody may provide a minimal example it would make me really happy!

FYI: The admin frontend is based on angularjs.

1

There are 1 answers

1
laggingreflex On

This can be done easily with Passport and Passport.SocketIO.

With Passport you want to authenticate the users, or at least your admin user, and set appropriate flag like user.admin = true

Then with passport.socketio which enables you to get the same user object in socket connection, you can easily verify whether the user is your admin user or not, and set appropriate listeners/emitters.

io.on('connection', function(socket){
    var user = socket.request.user; // with passport.socketio
    if(user.admin) {...}
});

More details on how to set it all up:

Passport allows you to authenticate a user. That usually requires the client to either register with an ID/password or over OAuth through google/facebook etc.

If the client doesn't (yet) chooses to, or you simply don't want registration process, but still want a user, what you want to do is create and login a randomly generated user.

app.use(function login(req, res, next){
    if(req.user) return next(); // user already present.

    var user = new User(/*randomness*/); // your new random user creation mechanism
    req.logIn(user, next); // login the user
});

req.logIn method gives you more control to login the user than using passport.local strategy (which it itself uses internally).

Note: Your user should have an id property, which is required for de/serialization.

So now you'll have every user who first visits your site automatically logged in with a randomly generated user object. It's available as req.user in each middleware/request-handler.

Now Passport.SocketIO plugin for Socket.IO allows you access to the same user object as socket.request.user in your socket connection handler.

Your configuration should look something like this:

var io = require('socket.io').listen(server);
io.use(require('passport.socketio').authorize({
    cookieParser: cookieParser,
    secret: secretSauce,
    store: sessionStore,
    fail: function(d,m,e,accept){accept(null, false)},
}));

Note the cookieParser, secretSauce, and if you used sessionStore should be the same as those that you used in your Express app, something probably like this:

var cookieParser = require('cookie-parser');
var secretSauce = 'Your Secret Phrase';
var session = require('express-session');
var sessionStore = new require('connect-mongo')(session)({url:'mongodb://localhost/app'});
app.use(cookieParser());
app.use(session({secret: secretSauce, store: sessionStore, saveUninitialized: true, resave: true}));

With all that set up, you now have access to the same user object in both your Express middlewares and your Socket.IO connection handler.

io.on('connection', function(socket) {
    var user = socket.request.user;
});