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

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.

Related

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.

socket.io : associate browser and computer with the connection

I am writing a game in node.js with socket.io library. It has a server to whom 2 clients connect and play. My game is working fine, but there is a problem.
If a client that is already connected connects again to the game it is considered as 3rd connection request which messes things up.
This usually happens when I restart my node server when client browsers were not closed. I do I get around this.
You can use cookies. There are modules for this: Socket.IO Authentication
But you can also do it manually, as it is a simple cookie:
When a user connects, add a step to identify the user before starting the game. This step should create a cookie or use the existing one and send it to the server for authentication.
It's not difficult, you can read and write cookies with javascript, and sending a String/number to the server is not a problem either (websocket.emit('auth',whatever)).
Based on this example, it looks like its possible to use cookies to identify sessions in socket.io, but you may be better off using query string values to identify a particular browser or computer:
https://www.exratione.com/2013/05/the-use-of-cookies-versus-query-string-tokens-to-identify-sessions-in-socketio/

send Session Description from node server to client

Do I need to use a websocket to send JSON data to my client? (it's a tiny session description)
Currently my client-side code sends a session description via XHR to my Node.js server. After receipt, my node server needs to send this down to the other client in the 'room'.
I can achieve this using socket.io, but is it possible to do anything a bit faster/ more secure, like XHR for example?
If you just want to receive the offer from the other side and nothing else, I would suggest you to try HTML5 Server Sent Events.
But this may bring problems due to different browsers support, so I would use a simple long pooling request. Since you only want to get the SDP offer, the implementation is pretty simple.
No, you don't need to use the WebSocket API to send JSON data from client to client via a server, but unless you use Google's proprietary App Engine Channel APIs, then the WebSocket API is probably your best choice.
Also, please keep in mind that you're not only sending session descriptions, but also candidate info (multiple times) as well as other arbitrary data that you might need to start/close sessions, etc.
As far as I know, the WebSocket API is the fastest solution (faster than XHR) for signalling because all the overhead involved with multiple HTTP requests is non-existent after the initial handshake.
If you want to code things yourself, I'd start reading the latest WebSocket draft and learning how to code the WebSocket server-side script yourself or else you will pretty much have to rely on a WebSocket library like Socket.IO or a proprietary solution like Google's App Engine Channel APIs.
How about using the 303 HTTP status code?
The first client send the session description to resource X, the server acknowledges the receipt and responds with a 303 status code that points to a newly created resource Y that accumulates other clients session descriptions.
The first client polls resource X until it changes.
The second client send its session description to resource A, the server acknowledges the receipt and updates resource Y. The first client notices the update with the next poll and will now have the second client's session information.

Retrieve Socket.io Client from Redis

I'm building a real time data system that allows an Apache/PHP server to send data to my Node.js server, which will then immediately send that data to the associated client via socket.io. So the Apache/PHP server makes a request that includes the data, as well as a user token that tells Node.js which user to send the data to.
Right now this is working fine - I've got an associative array that ties the user's socket.io connection to their user token. The problem is that I need to start scaling this to multiple servers. Naturally, with the default configs of socket.io I can't share connections between node workers.
The solution I had in mind was to use the RedisStore functionality, and just have each of my workers looking at the same Redis store. I've been doing research and there's a lot of documentation on how to use pub/sub functionality for broadcasting messages to large groups (rooms). That's fine, but I need to be able to send messages to a single client, so I need some way to retrieve a user's socket.io connection from the RedisStore.
The only way I can think to do this right now is to create a ton of 'rooms' named with the user's token, and only have one user in each room. Then I could just emit to that room. However, that seems very inefficient.
Is there a better way that I can retrieve user's unique socket.io connections from Redis?
Once a socket connection is made to a server running the node server, it is connected to that instance.
So it seems you need to make a way for your php server to know which node server a client is connected to.
In your redis store you could just store the id of the server as the value by the client id. Then php looks up which node server to use and makes the request.

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