Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authentication with Node/Express/Socket.IO

I have a node/socket.io/express server that's connected to a HTML file (like so). So visiting the web address connects you to the server. I am trying to set up a system where by, said server is being run on multiple computers at a time and by way of some sort of username and password authentication, visiting the webpage with specific credentials connects you to one of the computers with those same credentials running the server.

Ive seen mention of "Redis" from previous similar questions but they are pretty old and im wondering if there is a newer or better way of achieving this.

like image 446
Marcus Avatar asked Dec 03 '22 18:12

Marcus


1 Answers

You won't find a lot of up-to-date documentation since Express 4 is kind of new, so let me try to remedy that here :

Authentication in Express 4.x and Socket.IO 1.x

Let's start with a confusion I think you're making:

  • What is Redis?

    Redis is a data structure engine. It allows you to store key/values pairs, nothing more (In this context). The only thing it can do for you when building your authentication system is storing the data, user info, session ids, etc. In your case, you can share a store between multiple machines, the same way you'd share a database, or a text file.

    Redis

  • Authenticate user to node/express server

    One of the ways you can do that is by using passport. Passport is a middleware dedicated to authentication on Node.js. It is made for use with Express and relatively easy to setup. There is an excellent tutorial series on how to setup passport with your express application, so I won't detail this part, please take the time to go through the series, it's invaluable knowledge.

    Here's the link to the first part, which is the one I'll focus on for the next step.

  • Add socket.io to the mix

    Socket.io doesn't have access to the session cookies that you create in part 1. To remedy that, we will use the passport-socketio module.

    Passport-socketio requires a local session store, as opposed to a memory store. This means we need some way to store the session data somewhere, does that ring a bell?

    Exactly, Redis.

    You can try other stores, like mongoDB or MySQL, but Redis is the fastest.

    In this example, I'll assume that your express app and passport are already operational and will focus on adding socket.io to the app.

  • Setup :

var session = require('express-session'); //You should already have this line in your app
var passportSocketIo = require("passport.socketio");
var io = require("socket.io")(server);
var RedisStore = require('connect-redis')(session);
    
var sessionStore = new RedisStore({ // Create a session Store
   host: 'localhost',
   port: 6379,
});
    
app.use(session({
  store: sessionStore,  //tell express to store session info in the Redis store
  secret: 'mysecret'
}));

io.use(passportSocketIo.authorize({ //configure socket.io
   cookieParser: cookieParser,
   secret:      'mysecret',    // make sure it's the same than the one you gave to express
   store:       sessionStore,        
   success:     onAuthorizeSuccess,  // *optional* callback on success
   fail:        onAuthorizeFail,     // *optional* callback on fail/error
}));

Connect-redis is a session store package that uses redis (in case the name isn't obvious).

  • Final step :
function onAuthorizeSuccess(data, accept){  
  console.log('successful connection to socket.io');
  accept(); //Let the user through
}
    
function onAuthorizeFail(data, message, error, accept){ 
  if(error) accept(new Error(message));
  console.log('failed connection to socket.io:', message);
  accept(null, false);  
}
    
io.sockets.on('connection', function(socket) {
  console.log(socket.request.user); 
});

The user object found in socket.request will contain all the user info from the logged in user, you can pass it around, or do whatever you need with it from this point.

Note : This setup will be slightly different for Socket.IO < 1.x

like image 130
xShirase Avatar answered Dec 23 '22 13:12

xShirase