WebSocket security of incoming connection to clients - websocket

I have written WebSocket server with token authentication where the client connects as:
socket = new WebSocket("wss://websockets", ["hub", token] )
It uses subprotocol to squeeze auth token within headers.
On the server side I intercept this header key and authorize the request which works great - the client connects ok and keeps the connection open.
When token is not supplied, connection is rejected - great!
So in the typical use case: chat application, the user logins and gets authorization token to open the connection. Once connection is opened the client sends message to the server and the server sends that message to all connected clients.
So, so far I understand that the opening connection to the server and sending message to it is secured. What happens when that message is pushed to all connected clients? I donĀ“t need to be concerned about authorization of incoming messages (to the client) since the client needs to be connected and therefore authorized to receive those messages right?

Related

WebSocket Java Spring Boot Authentication with JWT

I am trying to build a chat web application. When the user sends a new message (HTTP Request) to the server, I want to send WebSocket notification to the receiver of the message (Angular Client). When the user logs in to the app it opens a websocket connection with the server. I would like to ask you if my logic is right or I can do something better. I want to intercept the handshake before it gets established and grab the session id of the websocket and the Session JWT cookie of the user, so I can store them in my database. So when a user sends a message, the backend should lookup database if there is active websocket connection or not. ALthough, I find this solution difficult to build as I am not sure a websocket session ID is enough to rebuild the Websocket session object from the start. Is there any better way to solve this?
Thank you in advance!

HTTPS over Socks5 server implementation

I am trying to implement a Socks5 server that could relay both HTTP and HTTPS traffic.
As the RFC1928 mentions, the following steps to establish a connection and forward the data must be taken :
Client sends a greeting message to the proxy.
Client & proxy authentication (assuming it is successful).
Client sends a request to the proxy to connect to the destination.
The proxy connects to the destination and sends back a response to the client to indicate a successful open tunnel.
The proxy reads the data from the client and forwards it to the destination.
The proxy reads the data from the destination and forwards it to the client.
So far, the proxy works as it should. It is able to relay HTTP traffic using its basic data forwarding mechanism. However, any request from the client to an HTTPS website will be aborted because of SSL/TLS encryption.
Is there another sequence/steps that should be followed to be able to handle SSL/TLS (HTTPS) traffic?
The sequence you have described is correct, even for HTTPS. When the client wants to send a request to an HTTPS server through a proxy, it will request the proxy to connect to the target server's HTTPS port, and then once the tunnel is established, the client will negotiate a TLS handshake with the target server, then send an (encrypted) HTTP request and receive an (encrypted) HTTP response. The tunnel is just a passthrough of raw bytes, the proxy has no concept of any encryption between the client and server. It doesn't care what the bytes represent, its job is just to pass them along as-is.

How to structure Socket.io Authentication

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.

Understanding timeouts in websocket sessions

websocket session is wrapped in a http session and so when the http session timesout the websocket session also times out.
However, when only the first call is a http call which is based on session cookie and the rest of the time it is a direct established connection,
how does the connection ever close in case of a timeout?
Scenario - We have a reverse proxy that manages the validation check on the sessions. This means it intercepts each call and checks for the validity of the session.
In case the cookies have expired, it returns a 401.
Since I have integrated websockets to this system, the initial websocket call goes through this reverse proxy with a valid cookie, upgrades the request to websocket and thereafter
keeps sending messages directly. The reverse proxy is not aware of these direct messages sent over WS.
Now when the http session expires, the other calls being made to the system get a 401. However the WS connection above does not know about it at all and continues to send/receive messages.
In case of a logout, an invalidate is called on the http session and so all the bound objects are notified and I get a SessionDisconnectEvent. However in case of timeouts I have no indication at all.
How should I terminate the WS connection in such cases?
Stack - spring + sockJS + basic stomp
My observations are that all the websocket sessions that are bound to the http session are not terminated in case of logout. Only the one that initiated the logout gets the SessionDisconnectMessage.
In case of timeouts, there are no indications at all.
To handle timeouts, I make a call to the server soon after I get a message at the client side and look for a 401 on this call. If it returns a 401, I initiate a session close on the client side.
To handle logout, I maintain a map of the http session id and all the websocket sessions associated with it. When I receive a disconnect on any of the websocket sessions, I terminate all the other ws sessions associated with that http session.

Reverse pusher - secret needed to receive, not send

Pusher service works as illustrated here:
Does it make sense to use it in reverse direction (and switched data channels)? My use case is as follows:
end users (actually mobile, not browser) send messages to Pusher via HTTP-based REST API
my firewalled machine is connected to Pusher via WebSockets API, subscribes channel and receives messages in realtime
This way I can work with Sandbox plan (only 1 persistent connection is used) but mobile app must contain Puser app key.
From what I understand, anyone can use this key to register subscribe same message stream via websockets. Is there a reverse mode, where receiving messages requires knowing the secret? Maybe other service would suit better?
A more secure solution would be for the mobile clients to use client events. Client events can only be triggered on private channels where the subscription to the channel has to be authenticated.The authentication requests should got to an HTTP endpoint that you control so that you can validate the subscription request.
You firewalled machine can either then have a WebSocket connection and receive the client events over that connection. Or it could receive the client events via client event WebHooks if it exposes an HTTP endpoint.

Resources