How to identify (un)successful authentication in Socket.IO (via socketio-auth)? - node.js

I'm trying to implement Websocket authentication in a Node.js server with the help of Socket.IO and socketio-auth. My testbed is a simple chat, where the client needs to send a password to the server to get permission to join. I do that via socketio-auth as follows:
Client side:
socket.on('connect', function(){
socket.emit('authentication', {client: "client", password: "test"});
});
Server side:
require('socketio-auth')(io, {authenticate: function(data, cb){
cb(null, data.password == 'test');}
})
This works as expected. As is, it allows the client to join. If I send the wrong password, the connection gets rejected.
However, I don't know how to collect the data from the server telling the client that it does not have permission to connect. All I get now is a POST on the client console saying '400 Bad request'. How can the client detect it has been denied access?
Thanks,
Jan

I figured out how to detect the error: Since the server kills the connection, one can simply listen for the 'disconnect' event:
Client:
socket.on('disconnect', function(error) {
console.log(error); // "io server disconnect"
})
This of course would fire whenever the socket gets disconnected, for any reason. One way to avoid this is to listen first for the "authenticated" event that gets fired on a successful connection with proper authentication. Inside one simply overrides the 'disconnect' event:
Client:
socket.on('authenticated', function() {
socket.on('disconnect', function(error) {
// override
})
})

Related

How to detect reconnect event in Socket IO

Whenever a client connects, I assign an id to that client using socket.id, and maintain it in the server for future reference. The problem I'm having right now is with disconnect/reconnect. I'm not even sure how to simulate this scenario, because if I reload the client page, it's technically creating a new client and connect to the server with different id. If I disconnect and connect the client manually then the client will again have a different id (socket.id).
I set up 'reconnect' event on both client and server using socket.on('reconnect',function(){...}), but it never seems to get called, given what I tried above.
So how would you go about simulating this scenario? And then what's the best way to detect if this new client is actually the same client that has disconnected?
There is a reconnect event on the client side inside which you can emit to the server and find the the reconnected client
socket.on('reconnect', function () {
console.log('you have been reconnected');
// where username is a global variable for the client
socket.emit('user-reconnected', username);
});
on the server you can get that as
socket.on('user-reconnected', function (username) {
console.log(username + ' just reconnected');
});

Socket.io client behavior when server is unreachable

I was wondering what is the default behavior when socket.io-client can't connect to the server and no callback is provided on the error.
Does the client indefinitely try to reconnect until it can reach the server?
I noticed that If I run this code on client before launching the server. As soon as the latter is started it receives the 'doSomethig' evnt.
socket.on('connect', function () {
socket.emit('doSomething', data);
socket.destroy();
});
How can I prevent the server to receive data emitted before it was started?
socket.on('connect_error', function () { socket.destroy(); });

Leaking sockets (sockets.io)

I have a client that connects to a socket server (node.js). I seem to being leaking sockets.
Here is the flow that causes the leaked sockets.
Connect to socket server
Signout (I see the log out confirmation on the server)
Signin in again to the socket server (see confirmation on socket server)
Restart socket server quickly (force restart using supervisor module by resaving a file)
Client reconnects to socket server. I now see 2 sockets that have connected to the socket server, instead of what should be just one.
If I repeat steps 2-4, I can see multiple connections from the same client.
Here is my client socket.io code:
client.js:
function start_socket(tok){
console.log("socket trying to connect");
//try every second to reconnect
socket = io.connect(sockets_host, { query: $.param({token: tok}), 'forceNew' : true, 'reconnection limit' : 100, 'max reconnection attempts' : 'Infinity' });
socket.on('connect', function() {
console.log('connected to socket server');
set_loggedin_status('true');
});
socket.on('disconnect', function() {
console.log('disconnected from server');
set_loggedin_status('false');
close_socket(); //get leaked sockets, wether I call this or not, though less if I do...
});
socket.on('error',function(err){
console.log('socket error: ' + err);
attempt_login();
});
}
function close_socket(){
console.log("in close socket");
socket.disconnect(true);
set_loggedin_status('false');
}
I've tried the above without 'forceNew' : true,, but then I seem to have problems signing in again after the client signed-out.
If I call close_socket from within the disconnected event (and not just from elsewhere when the client chooses to signout), I seem to get fewer leaked sockets, but still get them.
How am I creating multiple sockets?
The solution, though not necessarily the answer to the question, was in my case to use socket.io.disconnect() instead of socket.disconnect().
However, this meant if the socket server goes down once i've already established a connection, that no reconnects were being tried. So, I have to handle this situation myself if using this approach to solve the leaking sockets.

Socket.io fires connect event just after the second connect

I'm using socket.io with the latest version of node.js and socket.io shows an curious behavior:
The connect event fires on client side but not on server side for the first time.
After a reload or simply loading the page again the event got fired on both - client and server - side correctly.
What's wrong (with my code?)?
// Client
var socket = io.connect(window.location.protocol + '//' + window.location.hostname, {
'sync disconnect on unload': true
});
socket.on('connect', function() {
alert("Connect");
// Do other stuff
});
-
// Server
io.sockets.on('connection', function(socket) {
console.log("connection");
io.sockets.on('connect', function(socket) {
console.log("connect");
});
});
Started the server and loaded the page:
Client fires the alert, server just logs connection. Now loading the page again, it logs both connection and connect.
Update:
It seems that just the very first connection has such issues, afterwards it works everywhere as expected. Just after every node server (re)start, that behavior appears.
Note: node itself delivers the page where the socket.io is used and that works even on the first request, so a node issue should be excluded then.
Browser is also doesn't matter, it's the same on every browser.
For Socket.IO, connection is the server-side equivalent of connect on the client side. Therefore, when you're inside the callback for the connection event, the socket has already established a connection and you don't need to listen on some other event. I'm not sure what connect on the server side is, but it is not documented and does not work.
// on the server
io.sockets.on('connection', function(socket) {
// this connection has already been established
// no other handler is required
});
// on the client
var socket = io.connect();
socket.on('connect', function() {
// the connection has been established
});

Socket.IO is not triggering the connect event

I'm trying to setup a Socket.IO server, and right now, connecting doesn't seem to be working the way it does in the Wiki. I'm connecting to a server using the namespace /client, and I'm successfully seeing the connection made in the debug log, but the connection message is never display (and the other contents are never getting attached).
Server-side
var clients = io
.of('/client')
.on('connect', function (socket) {
// This is never getting run
console.log('Client connected');
});
Client side
var socket = io.connect('http://localhost:8082/client');
Why, in the above code, am I not getting the 'Client connected' message in my console?
So, turns out this is a very simple issue, as I suspected. The client uses the connect event, but the server uses connection.
The code should look like:
var clients = io
.of('/client')
.on('connection', function (socket) {
// This is never getting run
console.log('Client connected');
});

Resources