8
votes

I'm going to try to authenticate a connection on socket.io.

Currently, the user is first authenticated via a REST API, then, I send the user a JsonWebToken with the authenticated user's username. After I open the connection between the client and the server, my plan is to temporarily delete that socket from the list of connected sockets to prevent the receiving and sending of data between the server while I carry out the auth.

In this auth, I verify the token and if the token is valid I re-add the socket's id to the list of connected sockets. The only problem is that the first part doesn't work. I can't seem to delete the socket from the list.

To test this I did the following.

io.on('connection', function(socket){
    //temp delete socket
    delete io.sockets.connected[socket.id];
    console.log(io.sockets.connected);
    socket.emit("test");
});

As you can see I delete the socket and emit a test event to see if the socket is still open. The message was received by the client when it shouldn't be.

Does anyone know why this occurs?

2
if the socket is still open. Then it always listening .Before that you should to confirm that all connection has been closed. If any of these do not close then live client will listen . thanks. - Maneesh Singh
You don't want to temporarily disconnect the socket. socket.io has an authentication scheme that you can plug in to so that the socket is never accepted if it doesn't authenticate. Keep in mind that all webSocket connections start with an http request so if you're already authenticated via http, you can use that for the webSocket too. Also deleting a socket from io.sockets.connected does not disconnect the socket. - jfriend00
I use the rest api to authenticate a user so they can use the service. As far as I know, I can authenticate the user but I can't authenticate the socket.io session the same way. My idea was to use tokens to assure that the person using the socket is the one that is authenticated - Alex Catchpole
See this article for an example. If you set a cookie when the rest api is authenticated, then you can access that cookie in the socket.io middleware to determine authenticated or not. Or, you can launch a separate auth process from the socket.io middleware. The ability to access http cookies or do your own auth is built into socket.io so you don't have to disconnect while you do auth, you can just auth as part of the connection process. - jfriend00
let me create a example how you can auth your socket clients with the same token used with http server. - Wilson

2 Answers

11
votes

Try using disconnect method from the socket object, something like this:

io.on('connection', function(socket){
    //temp delete socket
    socket.disconnect();

    console.log(io.sockets.connected);
    socket.emit("test");
});

UPDATE:

For example if your HTTP server gives to a client a token:

app.post('/api/users', function (req, res) {
  var user = {
    username: req.body.username
  };

  var token = jwt.sign(user, secret, {expiresInMinutes: 30});

  res.json({token: token});
});

then you can reuse that token to authenticate your websocket connections.

The token sending code from the client (html file) will be:

socket = io.connect('http://localhost:4000', {
  query: 'token=' + validToken,
  forceNew: true
});

and the socketio authorization code in the server(socketio) will be:

// here is being used a socketio middleware to validate
// the token that has been sent
// and if the token is valid, then the io.on(connection, ..) statement below is executed
// thus the socket is connected to the websocket server.
io.use(require('socketio-jwt').authorize({
  secret: secret,
  handshake: true
}));



// but if the token is not valid, an error is triggered to the client
// the socket won't be connected to the websocket server.
io.on('connection', function (socket) {
  console.log('socket connected');
});

Note that the secret used on the express to generate a token, the same token is being used too on the validation token at socketio middleware.

I have created an example where you can see how this kind of validation works, the source code is here: https://gist.github.com/wilsonbalderrama/a2fa66b4d2b6eca05a5d

copy them in a folder and run the server.js with node and then access the html file from the browser at this URL: http://localhost:4000

but first install the modules: socket.io, express, socketio-jwt, jsonwebtoken

0
votes

socket.io also saves the sockets in a namespace (the default if not specified) and there's where you need to delete it for it to stop receiving messages.

See this post for a step by step explanation of what you're trying to do, and this module that abstracts the whole process.