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?
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 } });
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With