Socket IO authorization

I’d like to finish my story about my experiments with nodejs and socket.io. Check out my previous post http://radzserg.com/2014/07/01/socket-io-1-0-emitting-events-from-php/ .The last thing that I wanted to do is authorization. So imagine the following task we want to get updates for specific organization. My idea was quite simple in this case we can send authorization data (username:password or oauth token) to server plus send extra param like organization id

// let's add this param on frontend 
 var socket = io('http://localhost:8000', {
    query: "token=[oauth token]&organizationId=" + organizationId,
    transports: ['websocket']
});

Let’s add DB service that actually will perform authorization

var config = require('./src/config.json')
var pg = require('pg')
client = new pg.Client(config.pg.cdn);
client.connect(function (error) {
    if (error) {
        return console.error('could not connect to postgres', error);
    }
})

var dbService = require('./src/services/postgres_service.js')(client);

io.set('authorization', function (handshakeData, cb) {
    dbService.isUserAuthorized(handshakeData._query, function (result, error) {
        if (error) {
            return cb(error, false);
        }
        return cb(null, result);
    });
});

io.on('connection', function (socket) {
    // if we pass authorization join socket to organization room 
    socket.join("organization." + socket.request._query.organizationId);
});

An example of DB service could looks like this


module.exports = function (client) {

    return {
        isUserAuthorized: function (data, next) {
            var token = data.token ? data.token : null;
            if (!token) {
                return next(false, "Token must be specified");
            }
            var organizationId = data.organizationId ? data.organizationId : null;
            if (!organizationId) {
                return next(false, "organizationId must be specified");
            }

            var sql;
            sql = 'SELECT user_id FROM oauth_access_tokens WHERE access_token = $1 AND expires > NOW()';
            var query = client.query(sql, [token], function (error, result) {
                if (error) {
                    return next(false, error);
                }
                var userId = typeof result.rows[0] !== 'undefined' ? result.rows[0]['user_id'] : null;
                if (!userId) {
                    return next(false);
                }
                // then required queries to check if user has access to required organization. 
                // ... 
                return next(true)              
            });
        }
    }
};

Finally on PHP side we also can send events to specific room

$this->_emitter()->in("organization.{$orgnizationId}")->emit("news", [
     'data' => $data
]);

For now that’s it. Make a pause with nodejs. Although it was nice to play with it.

Leave a Reply

Your email address will not be published. Required fields are marked *