Is socket.io data emitted from server protected? - node.js

So I'm just learning socket.io and I think I know just enough to be dangerous. I've built a test (Node/Express) application that first takes you to a login page, then redirects you to an account page, after authenticating. The account page view is on a protected route, and it listens for a particular event emitted from the server and then displays that data in the browser. My question is if the data is being emitted from the server, can't it be listened for outside of the protected /account route and then viewed if someone knows the name of the event? If so, rendering the account view on a protected route is useless and I need to figure out how to authenticate a user before allowing the server to emit the data...right?
To clarify, my setup is as follows:
From server.js -
io.on('connection', (socket) => {
console.log('New user connected...');
socket.emit('data', {
//data emitted
});
});
From account.js (one of the js source scripts for my account.hbs view) -
socket.on('data', function (data) {
//do some stuff with the data
});

You haven't really disclosed enough for us to offer you info on your exact scenario so I'll generally describe how this works and what you do and don't need to worry about.
If you run your socket.io connection using TLS, then all data is protected in transit and cannot be snooped on by a middleman attack. If your socket.io connection is not TLS, then data is visible to network snoopers.
It is not enough to protect only the /account route form which a socket.io connection is made. You also have to protect the socket.io connection itself. Otherwise, any code jockey can write up a script that will make a socket.io connection to your server and you will happily let it connect and send it data. You need authentication on the socket.io connection itself. socket.io offers middleware support for that and if you already have an authenticated session for the /account page, then you can implement middleware that requires that authenticated session before allowing the socket.io connection. Then, you will have auth support for socket.io connections.
My question is if the data is being emitted from the server, can't it be listened for outside of the protected /account route and then viewed if someone knows the name of the event?
If your socket.io connection is not running an encrypted channel such as TLS, then it can be snooped on. Someone doesn't have to know the name of the event (it can be seen other ways) and it would be relatively easy to figure out the message name by just looking at the client JS in your web page.
If so, rendering the account view on a protected route is useless and I need to figure out how to authenticate a user before allowing the server to emit the data...right?
I wouldn't say useless, but it's not sufficient to provide protection for the socket.io connection. That connection needs it's own auth implementation which can likely piggyback on the same auth you did for the /account page.
Summary: Run socket.io on TLS (support https on your server and use an https://xxxx URL to connect for socket.io) and then implement authentication for your socket.io connections.

Related

How use app.use in io.on?

How I can use app.use in socket.io? E.g.
io.on('connection', function(data){
app.use('uri here', function(req, res){
// emitting here
});
});
It's really?
I have:
ss1.example.com (head-server for caching online users with users servers).
ss2.example.com (first app server)
ss3.example.com (second app server)
You're misunderstanding something here. The sequence of events when a web page is loaded is as follows:
User initiates page load (by clicking on something or by typing something in the URL bar or by selecting a bookmark).
Browser parses the server, gets the host and port out of the URL and sends an http GET request for the path to the IP address for that host and port.
Web server receives the GET request and sends back to the browser an HTML page.
The web server may or may not use middleware when that request is received (depending upon what it wants to do).
Browser parses the HTML page and then runs scripts in the page.
Javascript in the web page runs and initiates socket.io connection to some host (often to the same host that the web page came from).
Web server receives socket.io request and socket.io handle recognizes the web request as a socket.io connection request.
Server-side socket.io code responds to client request for socket.io connection and a socket.io connection is initiated between browser and server.
Client or server can then send data over the socket.io connection.
Now, to your question about where to insert app.use(). That is for http middleware. You would insert that in the regular web server request chain, typically right before you app.get() and app.post() request handlers. You would not typically use http middleware for a socket.io connection.
If you wish to run some code before any socket.io connection connects, then you would use io.use() and use a socket.io middleware handler. That will give you access to the http request information on every socket.io connection request.
If you wish to run some code on every socket.io message that is received (regardless of the message name), that is not a supported feature of socket.io. There are some add-ons that hack into socket.io to allow you to essentially do a socket.on('*', ...) type event handler for all incoming socket.io messages, but that is not something that socket.io supports as a built-in feature.
If one of these options still doesn't sound like what you want, then please explain to use what actual problem you're trying to solve and we can better make a suggestion for that particular problem.
Note your question is a bit like an XY problem where you asked how to do what you think is the solution (using app.use() for socket.io) rather than describing the actual problem you want to solve. The problem with that type of question is that if you're wrong about the solution direction, then all we can really tell you is that you're wrong with that solution because you didn't describe the actual problem so we can direct you to the right type of solution. In the future, you will probably get better answers if you make sure to describe the problem you're trying to solve, not just the solution you're trying.

Socket.io: correct way for the server to reconnect the client

I'm building MEAN application with socket.io. When page is just loaded, socket connection is established and kept live while user navigates to various pages, thanks to single-page nature of the app.
The user information is available in my socket connection thanks to passport.socketio.
However, when user logs in or out, I want the connection to be re-initialized, since otherwise socket will contain obsolete data about the user. Currently, I tried to implement it in this way: when user logs in / out, server disconnects this particular client's socket by calling socket.disconnect();.
On the client side, I listen for disconnect event, and try to re-establish the connection, like this:
_socket.on('disconnect', function(reason) {
_socket.connect();
});
Ok, now, when user logs out or in, server disconnects the client, this client connects back, and user information in the socket is up-to date. So far, so good.
But, consider different case when connection is broken: server is restarted. Previously, it "just worked": when I stop my server, connection is broken, but when I start server again, connection is automatically re-established. But after I've added my _socket.connect(); call, it doesn't work anymore: connection is still down until I refresh the page in the browser.
I've checked that when server calls disconnect();, the reason given to disconnect handler is: io server disconnect. And when server stops, the reason is: transport close.
Ok, then, I've implemented my disconnect handler as follows:
_socket.on('disconnect', function(reason) {
if (reason === 'transport close'){
// don't do anything special
} else {
_socket.connect();
}
});
Now it works. But, all of it seems as absolute dirty hack. At the very least, the reasons given (io server disconnect and transport close) seem to be just human-readable strings, so they might change in the future, and this will cause my code to stop working. And, well, there should be better way to do this; I must miss something essential, but unfortunately I can't find any good documentation on socket.io.
So, the question is: what is the correct way for the server to reconnect some particular client?
Additionally, if you have any recommendations on resources to learn about socket.io, I'd appreciate it very much as well.

Differentiate between client connections with node?

I need to implement a server that can handle simultaneous connections from both a client app and a browser that share a common database, however the clients from the browser have different functions from the clients of the app. I would like suggestions if this is the best design implementation. I decided not to have a different server for the client app or from the browser for this same reason as I can foreshadow synchronization issues when retrieving/writing information form the database. Is there a way to somehow attach a string or other information in front of the http connection to be able to tell each apart?
when the connection is made to the server what should be done?
var server = http.createServer(function(request,response)
{
//Code to tell them apart
});
Your client app is the best place to start. Do you have control over the client app? If you can modify it to send a specific header, that may work. Otherwise, another way to do so is to differentiate between User Agents... If the client app will always have a specific UA, treat all requests with that UA as a client app request, and all others as a browser request.

Socket.IO Sign In

So I have an application which uses Socket.IO, and the client connects to the Socket.IO server using a token generated by the web server when the client made a request. This should mean that they Socket.IO connection is now secure for this user.
I was wondering if it was practical to do user authentication (signing in/out) through Socket.IO alone meaning no POST. The client would send send an event like io.emit('authenticate', { ... sign in data ... }); and the Socket.IO would check the credentials and if it was verified, it would manually set the session data through the session store.
Is this way of doing this secure, or should the traditional POST for signing in/out still be used?
Doing it via Socket.IO is just as secure as an HTTP POST simply due to the fact that an HTTP POST has zero security built into it. You need to make sure that this process is secure and neither HTTP POST nor Socket.IO will help you with that at all.

How to authenticate with express and socket.io with TOKENS and not with COOKIES.

I'm building a realtime mobile app (native) and I'm interested in starting the app from a user login screen and then move on.
I figured I need Express + primus with socket.io (or sockjs) + passport.socketio + redis (not 100% sure I need redis yet) to build my backend.
I even found this step by step tutorial which is really helpful, it takes me step by step to making a secure api.
My question is a double one:
How can I tweak this example to use TOKENS instead of cookies (since I'm building a native mobile app and not a browser web app) and its more secure according to this.
How to bind express with socket.io - in other words, how does socket.io get to know if the user is authenticated or not?
I welcome any comment or advice.
Thank you.
First, I would use a different websocket library instead of socket.io. The socket.io developers are currently working on engine.io and socket.io appears to not be very actively maintained. I've experienced many of the issues described in the following links and since moving to sockjs have not had any problems.
http://www.quora.com/Sock-js/What-are-the-pros-and-cons-of-socket-io-vs-sockjs?share=1
https://github.com/LearnBoost/socket.io/issues
https://github.com/ether/etherpad-lite/issues/1798
http://baudehlo.com/2013/05/07/sockjs-multiple-channels-and-why-i-dumped-socket-io/
You may have to implement your own custom events on top of sockjs, but that's pretty trivial. Since it sounds like you're already using redis then implementing rooms and pub/sub should be pretty easy too.
Here's how we do our token based socket authentication.
First the client makes an HTTP request to the server to request a token. This routes the request through express' middleware and gives you easy access to the session data. This is where you would interact with passport to access their account or session data. If the user is logged in then generate a UUID and store their session data in redis as a key/value pair where the key is the UUID and the value is their stringified session/account data. Only send the UUID back to the client.
When the client first creates a websocket connection set a flag on the socket that marks it as unauthenticated.
When a message comes in on a socket check to see if the socket is authenticated. If not then check for a token in the message. If it doesn't exist then kill the connection. If it does then query redis for the key/value pair keyed by the token. If redis returns any data then you now have the session data for that user and can attach it to the socket and mark the socket as authenticated. If there's nothing in redis keyed by the token then kill the connection.
Now when you perform any operations on a socket you should have access to the session data for that user.

Resources