Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authentication methods over sockets

I'm trying to get authentication working over sockets with sailsjs and passport.

The challenge seems to be the fact that a socket connection doesn't have a session, and that sailsjs mocks a request object, causing it to not have Passport middleware setup. This caused nodejs to throw an error, saying that the req object didn't have a method called logIn.

So, I've tried following the code snippet as provided by @xdissent here: Sails.js + Passport.js authentication through websockets which, indeed allows me to sign in without throwing errors. Or does it..? It turns out that it does something, But I have no idea what. Because upon fetching req.user through a different (socket) request, I get an empty object returned.

I've looked in redis, too. This came out of it:

redis 127.0.0.1:6379> keys *
1) "waterline:broadcasting:_sequences:id"
2) "sess:aDJI0YHzh17E3AMjtKsZSijs"
redis 127.0.0.1:6379> get "sess:aDJI0YHzh17E3AMjtKsZSijs"
"{\"cookie\":{\"httpOnly\":true,\"path\":\"/\"}}"
redis 127.0.0.1:6379>

So there is a session, just no user stored in it.

So long story short, how do I get Passport and sailsjs to play nice over sockets.

Update: I'd like some information about sessions, sockets and cookies with sails in general. So if I set stuff in a session, and refresh the browser, I'd like it to still be there. If I make an xhr call on the same page as the socket connection, shouldn't that be the same session?

like image 756
Wesley Overdijk Avatar asked Jan 28 '14 19:01

Wesley Overdijk


People also ask

How do you authenticate a socket?

To authenticate socket.io connections using JWT, we send the token with the socket.io client. And then on the server, we check the token. const { token } = sessionStorage; const socket = io. connect('http://localhost:3000', { query: { token } });

Does socket IO need authentication?

It is important to know that, by default, there is no authentication provided by Socket.io connections. Anyone can point a client at your server and start emitting and receiving events.


1 Answers

Thanks to Kasper Isager there will be a passport generator for sails.js in the near future (Sails.js Version 0.10).

He implement Passport by using policies (sails middleware).

api/services/passport.js

var passport = require('passport');

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

passport.deserializeUser(function(id, next) {
    User.findOne(id).done(next);
});

// Put your Passport config logic here

// Make passport globally available
module.exports = passport;

api/policies/passport.js

module.exports = function (req, res, next) {

  // Initialize Passport
  passport.initialize()(req, res, function () {
    // Use the built-in sessions
    passport.session()(req, res, function () {
      // Make the user available throughout the frontend
      res.locals.user = req.user;

      next();
    });
  });

};

config/policies.js

module.exports.policies = {

    '*': [ 'passport' ],

    // MyCustomController: {
    //  update: [
    //      'passport',
    //      'authorize'
    //  ]
    // }

};

This will make the the passport request methods (logIn, etc.) available in socket requests as well.

After a successful login your server-side session object will look like this:

{
    // Express
    cookie: {
        originalMaxAge: null,
        expires: null,
        httpOnly: true,
        path: '/'
    },
    // Passport
    passport: {
        user: '52fc98e108b31348a537fa43' // userId
    }
}

You may access it in any policy with req.session or even on socket callbacks like:

config/sockets.js

onConnect: function(session, socket){}
onDisconnect: function(session, socket){}

If you want to see the Kaspers full implementation check out his repository: sails-generate-auth

like image 87
HaNdTriX Avatar answered Sep 30 '22 08:09

HaNdTriX