Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

socket.io authentication after socket established

socket.io authentication after socket established

Problem

I'm working on a small multiplayer game. I'd like to introduce authentication. I'm using Node.js and Socket.io.

When the user arrives that the main page - I want them to join the game whether they are logged in or not - but they will be unable to do anything within it (only watch).

How could I then go about authenticating the user on the already open socket?

Could I maintain the authentication still if they left the site and came back? Can you pass a Cookie through a web socket?

EDIT

To further my question. One of the possible thoughts I've had is to provide the websocket connection, then when they try to login in, it passes username and password as a message to the websocket.

client.on('onLogin', loginfunction);

I could then take the username and password, check against the database, then take the session ID of the socket and pass it somewhere to say that session is authenticated to that user.

Is this secure? Could I still implement a cookie on the socket so they could come back? Is there any way within socket.io of stating that the socket is now authenticated instead of manually checking on each message received?

Cheers

Problem courtesy of: Chris Evans

Solution

This isn't actually too hard, but you're approaching it the wrong way. A couple things:

  1. You cannot set a cookie with socket.io; you can, however, get the cookie values of any connected client at any time. In order to set a cookie, you will have to send a new http response, meaning the user must first send a new http request (aka refresh or go to a new page, which it sounds is not a possibility for you here).

  2. Yes: socket.io is secure (to the extent that any transmitted data can be).

As such, you can do the following:

On the user's initial connection, create a cookie with a unique session ID, such as those generated from Express's session middleware. You will need to configure these not to expire on session end though (otherwise it will expire as soon as they close their browser).

Next you should create an object to store the cookie session IDs. Each time a new connect.sid cookie is set, store in your new object with a default value of false (meaning that the user has been authenticated by session, but not by logon)

On the user's login, send a socket emit to the server, where you can then authenticate the login credentials, and subsequently update the session id object you created to read true (logged in) for the current socket id.

Now, when receiving a new http request, read the cookie.sid, and check if its value in your object is true.

It should look something like the following:

var express = require('express'),
http = require('http'),
cookie = require('cookie');

var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);


app.use(express.cookieParser());
app.use(express.session({ 
    secret: 'secret_pw',
    store: sessionStore,
    cookie: { 
        secure: true,
        expires: new Date(Date.now() + 60 * 1000), //setting cookie to not expire on session end
        maxAge: 60 * 1000,
        key: 'connect.sid'
    }
}));

var sessionobj = {}; //This is important; it will contain your connect.sid IDs.

//io.set('authorization'...etc. here to authorize socket connection and ensure legitimacy


app.get("/*", function(req, res, next){
    if(sessionobj[req.cookies['connect.sid']]){
        if(sessionobj[req.cookies['connect.sid']].login == true){
            //Authenticated AND Logged in
        }
        else{
            //authenticated but not logged in
        }
    }
    else{
        //not authenticated
    }

});


io.sockets.on('connection', function(socket){
    sessionobj[cookie.parse(socket.handshake.headers.cookie)['connect.sid'].login = false;
    sessionobj[cookie.parse(socket.handshake.headers.cookie)['connect.sid'].socketid = socket.id;

    socket.on('login', function(data){
        //DB Call, where you authenticate login
        //on callback (if login is successful):
        sessionobj[cookie.parse(socket.handshake.headers.cookie)['connect.sid']] = true;
    });

    socket.on('disconnect', function(data){
        //any cleanup actions you may want
    });

});
Solution courtesy of: Ari

Discussion

View additional discussion.



This post first appeared on Node.js Recipes, please read the originial post: here

Share the post

socket.io authentication after socket established

×

Subscribe to Node.js Recipes

Get updates delivered right to your inbox!

Thank you for your subscription

×