问题
I am using passport for authentication/authorization along with local strategy and a JWT.
Following some research (intensive googling ;) I understand that the best place for the authorization is to use a policy as it applies both for a regular HTTP requests and a socket request (through SailsSocket
object that can send 'virtual' HTTP-like requests).
I am now trying to figure out how to use sockets properly and I've seen that there's a beforeConnect
handler that allows to reject a connection. While it is not a big deal (as I have a policy that will prevent it from getting data), I want to be able to reject connections - I think its healthier and what reason is there to allow a non-authorized socket connection.
I only want to socket to connect after initial authentication so that in my socket initialization I can set the headers to include the JWT:
io.sails.url = connections.http.baseURL;
io.sails.headers = {
'Authorization': 'Bearer ' + token
};
io.sails.useCORSRouteToGetCookie = false;
io.socket = io.sails.connect();
io.socket.on('...', someHandler);
This seems to work fine - the socket request hits the JWT policy and I get a req.user in my controller methods for socket requests.
My question is - how do I go about rejecting the user without a token from connecting (and should I even do that?)
When I break inside the beforeConnect
I don't see the Authorization header in handshake object.
Update: furthermore, I am now trying to send the token in the query when connecting:
io.socket = io.sails.connect({token: token});
With that, I am able to see the token in the handshake. I'd expect it to be in handshake.query
which does not exists. Instead, it is available in handshake._query
while the sails docs (here) is claims that is should be under socket.handshake.query
(but socket
doesn't even exists in beforeConnect
and the default function footprint is beforeConnect: function(handshake, cb)
)
Are these bugs?? Am I missing something?
回答1:
Following discussion with one of the sails developer (here, thanks sgress454):
Headers are not sent with the initial request for connection. It is part of the socket.io specifications and not an issue with sails itself. It maybe possible with newest versions of socket.io to set
transportOptions
but this isn't integrated into sails yet (2017-04-02).Any query parameter appears as
_query
property of thehandshake
argument. This is not (currently) documented correctly. The documentation will be updated in the near future.
As for the underlying issue - I've implemented the token verification using my own code as I could not find a way to have passport.js integrated in the beforeConnect
method. In config/sockets.js
I have something like:
beforeConnect: function(handshake, cb) {
// `true` allows the connection
// (`false` would reject the connection)
var token = handshake._query ? handshake._query.token : null;
CipherService.verifyToken(token, function verifyTokenResults(err, decoded, info) {
if (err || !decoded) {
if (err.name === "TokenExpiredError") {
// token expired - user can't connect...
return cb(null, false);
} else {
// some other error...
return cb(err, false);
}
}
// here you may want to do other verification, e.g. the user is active
return cb(null, true);
});
},
I now have automatic reconnection issues :-( see here )-:
来源:https://stackoverflow.com/questions/42765635/sails-socket-authorization-using-passport