socket.io : associate browser and computer with the connection - node.js

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/

Related

Is socket.io implementation possible inside REST framework?

I am building an app in which I provide functionality X, Y and chat.
Lets say that X and Y are non-interactive eg. reading articles - which will work fine with REST (on a node.js server) while chat is obviously interactive so it will work best with socket.io!
Questions: 1. Is it possible for me to 'switch on' a socket between the server and the user when the user navigates to the chat part of the application? 2. Can I open up a socket inside a GET request for the url: example.com/chats/usr_id on the node.js server?
3. How can this be accomplished inside a Backbone routing framework?
Yes. Just initialize the connection when the view is rendered (via a controller or script). See socket.io client documentation. You can just connect when the view is rendered and disconnect when the view is terminated. http://socket.io/docs/client-api/
You cannot open sockets with a GET request. Socket.io has it's own build in mechanisms for connecting to a socket server. It will start with Web Socket protocol and fall back to Long Polling. You can however use custom url's for unique things. One again, consult the socket.io documentation: http://socket.io/docs/client-api/
http://www.sitepoint.com/chat-application-using-socket-io/
p.s. I'd suggest reading up on how Web Sockets work, as you don't seem to have a very strong understanding.

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.

How to handle sessions in node.js without frameworks

I'm working on a SPA (single page web app); the idea was to go lightweight and not use too much frameworks and abstraction and stuff, so I created the HTTP server for static+dynamic files and it works well. Now I have implemented socket.io in the web app, but I would like to know what in your opinion would be a good way of handling sessions (keeping in mind that socket io must be able to identify the user who calls functions and know to who it must push data).
Hope i've been clear enough :)
Socket.io has built in methods for saving server-side session data for a given socket via socket.get, socket.set and socket.del. Where it saves this data is by default a memorystore, but you can use redis, etc. Keep in mind that when the socket disconnects, that data doesn't persist on reconnect, so you'll want to send along client identifying data with your socket setup events or during auth.
So that leaves your client data, which can be persisted via localStorage, sessionStorage, or plain old vanilla cookies, among others.

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.

Resources