Socket.IO Sign In - node.js

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.

Related

How to build a fully secure login: do I need SSL?

context
I'm building a project to better understand login/security, and SSL is really tripping me up.
So far I have a front end (vue.js), an API (node/express), and a DB (postgreSQL).
This is the general auth flow:
When a user logs in they send an email and password (via Axios) to the API.
The API queries the database for a matching username and then using bcrypt.compare it checks the password that is hashed in the database.
If this is successful, the API signs a JWT and sends it to the client.
The client then saves the JWT in local storage and is used for future queries.
question(s)
So far I think that all of the above is the best practice EXCEPT for the first step. From the reading, I've done so far the client needs SSL to securely send a password to the API. Is this the case? Does my server also need to be SSL or just the client/host?
I'm ultimately going to try to use firebase hosting (which is automatically SSL) for the frontend, and heroku for the API and database. If there are more secure options I'm open to suggestions.
Also, in general, I'm new to all of this security stuff - If I'm missing anything or if something else isn't secure, I would love the advice!
SSL creates a secure connection between two points. In our scenario between the client, and the server. After some initial negotiation, the client encrypts its messages in a way that only the server can decrypt. And the server does the same with its answers, or its own questions. By using SSL between these two end points, nobody but the client and server can read the messages.
This is important, since a message sent between client and server is actually seen by many more machines/processes in between. Dozens of other processes can thus see the message, and if the message is not encrypted that means all those processes can know exactly what's in the message. When the client and server communicate over SSL, the other processes still see the messages, but they can't decrypt them.
To your concrete questions: the client opens a secure connection to the server. Both the client and the server need to support this. If you write a custom server, that means you'll need to ensure it has a SSL certificate. A very common place to get these for free these days is letsencrypt.org.

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.

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.

Should I be using socket.io for my nodejs application?

I am learning HTML5 and doing so by building a simple chatroom using Express, PassportJS, Mongoose/MongoDB, connect-mongoose, NowJS.
Everything works perfectly, except for one big problem: I am having trouble authenticating NowJS.
The usual way of doing this is to read the "this.user.cookie" property server-side and parse the string. However, for some reason, cookies is not being sent back to the server. (details here: NowJS cookie field in this.user is empty) After a lot of googling, I think there are no alternative, secured, way for me to authenticate NowJS connections/clients.
Question
I am thinking of stripping all of NowJS out of my web app, and using socket.io directly. Is socket.io easy with work with? Would I lose key functionality if I switch to socket.io, instead of using NowJS?
Can I use socket.io to:
1) Call server-side functions?
2) Share server-side variables with the client?
Socket.io does not share variables or allow you to call server side functions. It allows you to bind and emit events on the client side and server side.
As for your cookie not being sent, its most likely that its being considered a cors, cross domain request, this can happen if your using a different port for socket.io then the http server that set the cookie.

Express: Share session with websocket

I'm writing a chat application with node.js and Express. The authentication is working and I can login to user accounts and register new sessions. My problem is that the chat itself runs within a Websocket (Websocket-node) and I can't access the session data. How can I identify new connection requests made to the websocket without the session data?
Thanks!
I would advise not working with WebSockets directly and instead use Socket.IO. It has authorization and handshaking built in
https://github.com/LearnBoost/socket.io/wiki/Authorizing
Here is how you can get session information
http://www.danielbaulig.de/socket-ioexpress/

Resources