2
1
mirror of https://github.com/Thream/socketio-jwt.git synced 2024-07-21 09:38:31 +02:00
socketio-jwt/lib/index.js
Pieter Jan De Smedt dac693930b fix(lib/index.js) return auth.success
Next step would not execute because no function(socket, next) was returned in case of successful verification in the 'one roundtrip' (handshake) approach.
Returning auth.success instead of just executing it solves this.

Fixes #51
2015-10-08 14:06:33 +02:00

153 lines
4.1 KiB
JavaScript

var xtend = require('xtend');
var jwt = require('jsonwebtoken');
var UnauthorizedError = require('./UnauthorizedError');
function noQsMethod(options) {
var defaults = { required: true };
options = xtend(defaults, options);
return function (socket) {
var server = this.server || socket.server;
if (!server.$emit) {
//then is socket.io 1.0
var Namespace = Object.getPrototypeOf(server.sockets).constructor;
if (!~Namespace.events.indexOf('authenticated')) {
Namespace.events.push('authenticated');
}
}
if(options.required){
var auth_timeout = setTimeout(function () {
socket.disconnect('unauthorized');
}, options.timeout || 5000);
}
socket.on('authenticate', function (data) {
if(options.required){
clearTimeout(auth_timeout);
}
jwt.verify(data.token, options.secret, options, function(err, decoded) {
// error handler
var onError = function(err, code) {
if (err) {
code = code || 'unknown';
var error = new UnauthorizedError(code, {
message: (Object.prototype.toString.call(err) === '[object Object]' && err.message) ? err.message : err
});
socket.emit('unauthorized', error, function() {
socket.disconnect('unauthorized');
});
return; // stop logic, socket will be close on next tick
}
};
if (err) {
return onError(err, 'invalid_token');
}
// success handler
var onSuccess = function(){
socket.decoded_token = decoded;
socket.emit('authenticated');
if (server.$emit) {
server.$emit('authenticated', socket);
} else {
//try getting the current namespace otherwise fallback to all sockets.
var namespace = (server.nsps && socket.nsp &&
server.nsps[socket.nsp.name]) ||
server.sockets;
// explicit namespace
namespace.emit('authenticated', socket);
}
};
if(options.additional_auth && typeof options.additional_auth === 'function') {
options.additional_auth(decoded, onSuccess, onError);
} else {
onSuccess();
}
});
});
};
}
function authorize(options, onConnection) {
if (!options.handshake) {
return noQsMethod(options);
}
var defaults = {
success: function(data, accept){
if (data.request) {
accept();
} else {
accept(null, true);
}
},
fail: function(error, data, accept){
if (data.request) {
accept(error);
} else {
accept(null, false);
}
}
};
var auth = xtend(defaults, options);
return function(data, accept){
var token, error;
var req = data.request || data;
var authorization_header = (req.headers || {}).authorization;
if (authorization_header) {
var parts = authorization_header.split(' ');
if (parts.length == 2) {
var scheme = parts[0],
credentials = parts[1];
if (scheme.toLowerCase() === 'bearer') {
token = credentials;
}
} else {
error = new UnauthorizedError('credentials_bad_format', {
message: 'Format is Authorization: Bearer [token]'
});
return auth.fail(error, data, accept);
}
}
//get the token from query string
if (req._query && req._query.token) {
token = req._query.token;
}
else if (req.query && req.query.token) {
token = req.query.token;
}
if (!token) {
error = new UnauthorizedError('credentials_required', {
message: 'No Authorization header was found'
});
return auth.fail(error, data, accept);
}
jwt.verify(token, options.secret, options, function(err, decoded) {
if (err) {
error = new UnauthorizedError('invalid_token', err);
return auth.fail(error, data, accept);
}
data.decoded_token = decoded;
return auth.success(data, accept);
});
};
}
exports.authorize = authorize;