How to structure Socket.io Authentication - socket.io

I am creating an application using Flask-SocketIO at the server side and a javascript Socket.IO client. (There will also be a Python client later). I want to ensure users are authenticated before they connect to the web socket server.
I have created a PHP login form to check the username and password. If these are valid then a unique token is returned and the token is also inserted into a table on the server. The token is passed to the client side javascript, where it is submitted with the request to create a web socket connection.
As I understand it Flask-SocketIO will simply accept the connection and I need to put my validation code under the #socketio.on('connect') decorator. (I assume a server based implementation of Socket.IO works in a similar way). Therefore my code checks the submitted token against the database table and if it is valid the web socket connection is simply allowed to happen. However if the token is not valid I issue a disconnect() command. The javascript client does not try the connection again, which is what I want in this scenario.
Here is where it gets tricky...
I would like to write a disconnect handler on the client side using socket.on('disconnect', function() { //do something }); to allow the user to reconnect when the socket is broken due to a poor mobile connection for example. How can I distinguish an accidental disconnection from an intentional one due to failed validation?
Conversely, I would like to alert the user to the fact that their validation process failed. But how to distinguish that from a scenario where the the socket is broken due to a poor mobile connection?

I would like to write a disconnect handler on the client side using socket.on('disconnect', function() { //do something }); to allow the user to reconnect when the socket is broken due to a poor mobile connection for example.
There is no need for you to worry about reconnection. The Socket.IO client protocol includes reconnection support and will always try to reconnect when the connection is lost. To verify this, start your server, connect with a client, and then kill your server. A little bit later restart the server and you will see that in a matter of seconds the connection is reestablished.

Related

NestJS 8 Socket.io 4 have socket on the server side but not being reached

NestJS 8, socket.io 4
Client user has a socket being able to receive data from the server. Not sending.
Refresh browser, the socket ID changed. Socket on the client receive 'connect' event! Yet. On server side, no logging at all. Which kind of explained point 1.
After reboot nest, problem is gone. But it comes back eventually.
My current troubleshooting direction is
Was the connection on the client dead already and it's still trying somehow to update the socket?
Browser does some caching, service worker?
I hope someone can enlighten. This happens after upgrade to socket.io 4 from 2.
It's my own stupidity.
My tenant who own the namespace. In order to reach him, I create his namespace and send message to it no matter he's online or offline.
This works fine in socket.io 2. I don't know why.
What I should do, is to check whether or not, the namespace exists or not first.
That's why the issue that I have is that the server somehow seems able to pipe message to the namespace, yet the tenant cannot send the message to the server because the tenant was not initialized properly in the nest gateway.

Invalid session / Session is disconnected

What can be the reasons that cause a socket.io session to be crashed and server returns invalid session or session is disconnected ?
There is a specific situation that causes these problems with the session. When a client fails to send the pings at the expected interval the server declares the client gone and deletes the session. If a client that falls into this situation later tries to send a ping or another request using the now invalidated session id it will receive one of these errors.
Another possible problem with the same outcome is when the client does send the pings at the correct intervals, but the server is blocked or too busy to process these pings in time.
So to summarize, if you think your clients are well behaved, I would look at potential blocking tasks in your server.
Ok, I'll illustrate my problem in this figure project's architecture .
In fact, I have a websocket between the react app and the rasa ( tool for creating chatbots) based on flask. bot response need to access to an external API to retrieve some data. Here where things go wrong. Sometimes, these requests take too long to return a response, and that's when websocket misbehave.

When the server opens the socket connection it is flooded with messages from the clients

I start the server and the clients.
Then I close the server, and after few minutes reopen it.
I get too many messages (from the client).
How do I reset it, to start clean.
The server code:
var io = require('socket.io').listen(3001);
var games=[];
console.log('start1 server.js');
setTimeout(clear_games,30000);
io.sockets.on('connection', function(socket)
{
When your active socket.io clients lose the connection to the server, they will constantly try to reconnect until your server comes back online and they successfully get a reconnection. This is the normal and expected behavior and is generally a very useful features since the client will then automatically restablish a connect after a temporary server restart or interrupted network connection.
If you just want to start over for testing purposes, then close all the client web pages, shut down your server, then restart your server, then open the client web pages again. Because the client web pages will not be open when you start your server, it should not immediately get a bunch of reconnects.
If you never want the client to automatically reconnect, then you can specify that in an option in the client code that connects to the server with an option of {reconnection: false}, (though that is generally a bad idea because now the client won't auto-recover if the connection is temporarily interrupted).
What I did is:
In the client, I added a monitor function that is invoked (setTimeout) every second, and checks the socket.connected.
If it is not connected, I don't send any messages to the server till I see that it is true (connected) again.
This solved the problem.

How reconnect from server to client

I'am able to detect when client disconnect from a server by this code:
self._session.socket.on("close", function() {
console.log("client disconnected");
}
But how can I try reconnect to the disconnected client?
You cannot connect from server to client as client isn't listening to the websocket, but just connecting (to the server).
However, you can put a code in your client to reconnect it at onclose (or just close) event. Generally this occurs by recreating the WebSocket object in the client with the correct parameters.
Something as:
function connect(){
var mywebsocket = new WebSocket("ws://(your url)");
// ... my callbacks and functions...
mywebsocket.onclose = connect; // or arguments.callee
}
connect();
Should work correctly. ;)
Good luck.
If the client got disconnected for some reason (internet connection disruption/server issues) it will automatically reconnect on its own. To see how many attempts have been made or the status have a look at http://docs.meteor.com/#meteor_status
Since version 0.6.3 if the internet was disconnected. As soon as the internet is back it will attempt to reconnect too.
To reconnect from your code somewhere you can run Meteor.reconnect() from the client.
Unfortunately the meteor client can't listen for connections from the server so the server can't initiate a reconnection, you need some kind of connection to a server to send a message to the client to do something such as a reconnection.

Socket.IO : What is the recommended pattern for server side cleanup?

Is it enough to cleanup on disconnect? What happens if a browser disappears before sending an explicit disconnect?
What is the recommended pattern for server side cleanup, so that the resources bound to the connection are not leaked (e.g. Namespace)?
(using gevent-socketio, if it matters)
If you use WebSockets as transport, it would automaticaly disconnect the socket on browser close.
If you use xhr-polling for example it would not automaticaly disconnect (speaking about gevent-socketio).
My approach when xhr-polling is used was:
Saving the socket session id among with logged in user id in database
On next user login detect if such a record exists
Use the stored session id in the record to disconect the unused socket since the fresh user login would generate new socket
This is not rapid solution since you may have unused sockets connected until new login is performed by the user, but it performs a kind of cleanup when the user log in.
This article may be a hint to something more creative than mine solution: http://flask.pocoo.org/snippets/71/

Resources