restifyve-jwt
Version:
JWT authentication middlewarefor restify > 5.x.
262 lines (221 loc) • 9.24 kB
JavaScript
var jwt = require('jsonwebtoken');
var assert = require('assert');
var restifyjwt = require('../lib');
var restify = require('restify');
describe('failure tests', function() {
var req = {};
var res = {};
it('should throw if options not sent', function() {
try {
restifyjwt();
} catch (e) {
assert.ok(e);
assert.equal(e.message, 'secret should be set');
}
});
it('should throw if no authorization header and credentials are required', function() {
restifyjwt({ secret: 'shhhh', credentialsRequired: true })(req, res, function(err) {
assert.ok(err);
assert.equal(err.message, 'No authorization token was found');
});
});
it('support unless skip', function() {
req.originalUrl = '/index.html';
restifyjwt({ secret: 'shhhh' }).unless({ path: '/index.html' })(req, res, function(err) {
assert.ok(!err);
});
});
it('should skip on CORS preflight', function() {
var corsReq = {};
corsReq.method = 'OPTIONS';
corsReq.headers = {
'access-control-request-headers': 'sasa, sras, authorization'
};
restifyjwt({ secret: 'shhhh' })(corsReq, res, function(err) {
assert.ok(!err);
});
});
it('should throw if authorization header is malformed', function() {
req.headers = {};
req.headers.authorization = 'wrong';
restifyjwt({ secret: 'shhhh' })(req, res, function(err) {
assert.ok(err);
assert.equal(err.message, 'Format is Authorization: Bearer [token]');
});
});
it('should throw if authorization header is not Bearer', function() {
req.headers = {};
req.headers.authorization = 'Basic foobar';
restifyjwt({ secret: 'shhhh' })(req, res, function(err) {
assert.ok(err);
assert.equal(err.body.code, 'InvalidCredentials');
});
});
it('should throw if authorization header is not well-formatted jwt', function() {
req.headers = {};
req.headers.authorization = 'Bearer wrongjwt';
restifyjwt({ secret: 'shhhh' })(req, res, function(err) {
assert.ok(err);
assert.equal(err.body.code, 'InvalidCredentials');
});
});
it('should throw if authorization header is not valid jwt', function() {
var secret = 'shhhhhh';
var token = jwt.sign({ foo: 'bar' }, secret);
req.headers = {};
req.headers.authorization = 'Bearer ' + token;
restifyjwt({ secret: 'different-shhhh' })(req, res, function(err) {
assert.ok(err);
assert.equal(err.body.code, 'InvalidCredentials');
console.log(err)
assert.equal(err.jse_cause.message, 'invalid signature');
});
});
it('should throw if audience is not expected', function() {
var secret = 'shhhhhh';
var token = jwt.sign({ foo: 'bar', aud: 'expected-audience' }, secret);
req.headers = {};
req.headers.authorization = 'Bearer ' + token;
restifyjwt({ secret: 'shhhhhh', audience: 'not-expected-audience' })(req, res, function(err) {
assert.ok(err);
assert.equal(err.body.code, 'InvalidCredentials');
assert.equal(err.jse_cause.message, 'jwt audience invalid. expected: not-expected-audience');
});
});
it('should throw if token is expired', function() {
var secret = 'shhhhhh';
var token = jwt.sign({ foo: 'bar', exp: 1382412921 }, secret);
req.headers = {};
req.headers.authorization = 'Bearer ' + token;
restifyjwt({ secret: 'shhhhhh' })(req, res, function(err) {
assert.ok(err);
assert.equal(err.body.code, 'InvalidCredentials');
assert.equal(err.jse_cause.message, 'jwt expired');
});
});
it('should throw if token issuer is wrong', function() {
var secret = 'shhhhhh';
var token = jwt.sign({ foo: 'bar', iss: 'http://foo' }, secret);
req.headers = {};
req.headers.authorization = 'Bearer ' + token;
restifyjwt({ secret: 'shhhhhh', issuer: 'http://wrong' })(req, res, function(err) {
assert.ok(err);
assert.equal(err.body.code, 'InvalidCredentials');
assert.equal(err.jse_cause.message, 'jwt issuer invalid. expected: http://wrong');
});
});
it('should use errors thrown from custom getToken function', function() {
var secret = 'shhhhhh';
var token = jwt.sign({ foo: 'bar' }, secret);
function getTokenThatThrowsError() {
throw new restify.errors.InvalidCredentialsError('Invalid token!');
}
restifyjwt({
secret: 'shhhhhh',
getToken: getTokenThatThrowsError
})(req, res, function(err) {
assert.ok(err);
assert.equal(err.message, 'Invalid token!');
});
});
it('should throw error when signature is wrong', function() {
var secret = "shhh";
var token = jwt.sign({ foo: 'bar', iss: 'http://www' }, secret);
// manipulate the token
var newContent = new Buffer("{foo: 'bar', edg: 'ar'}").toString('base64');
var splitetToken = token.split(".");
splitetToken[1] = newContent;
var newToken = splitetToken.join(".");
// build request
req.headers = [];
req.headers.authorization = 'Bearer ' + newToken;
restifyjwt({ secret: secret })(req, res, function(err) {
assert.ok(err);
assert.equal(err.body.code, 'InvalidCredentials');
assert.equal(err.jse_cause.message, 'invalid token');
});
});
});
describe('work tests', function() {
var req = {};
var res = {};
it('should work if authorization header is valid jwt', function() {
var secret = 'shhhhhh';
var token = jwt.sign({ foo: 'bar' }, secret);
req.headers = {};
req.headers.authorization = 'Bearer ' + token;
restifyjwt({ secret: secret })(req, res, function() {
assert.equal('bar', req.user.foo);
});
});
it('should work if authorization header is valid with a buffer secret', function() {
var secret = new Buffer('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', 'base64');
var token = jwt.sign({ foo: 'bar' }, secret);
req.headers = {};
req.headers.authorization = 'Bearer ' + token;
restifyjwt({ secret: secret })(req, res, function() {
assert.equal('bar', req.user.foo);
});
});
it('should set userProperty if option provided', function() {
var secret = 'shhhhhh';
var token = jwt.sign({ foo: 'bar' }, secret);
req.headers = {};
req.headers.authorization = 'Bearer ' + token;
restifyjwt({ secret: secret, userProperty: 'auth' })(req, res, function() {
assert.equal('bar', req.auth.foo);
});
});
it('should work if no authorization header and credentials are not required', function() {
req = {};
restifyjwt({ secret: 'shhhh', credentialsRequired: false })(req, res, function(err) {
assert(typeof err === 'undefined');
});
});
it('should work if token is expired and credentials are not required', function() {
var secret = 'shhhhhh';
var token = jwt.sign({ foo: 'bar', exp: 1382412921 }, secret);
req.headers = {};
req.headers.authorization = 'Bearer ' + token;
restifyjwt({ secret: secret, credentialsRequired: false })(req, res, function(err) {
assert(typeof err === 'undefined');
assert(typeof req.user === 'undefined')
});
});
it('should not work if no authorization header', function() {
req = {};
restifyjwt({ secret: 'shhhh' })(req, res, function(err) {
assert(typeof err !== 'undefined');
});
});
it('should work with a custom getToken function', function() {
var secret = 'shhhhhh';
var token = jwt.sign({ foo: 'bar' }, secret);
req.headers = {};
req.query = {};
req.query.token = token;
function getTokenFromQuery(req) {
return req.query.token;
}
restifyjwt({
secret: secret,
getToken: getTokenFromQuery
})(req, res, function() {
assert.equal('bar', req.user.foo);
});
});
it('should work with a secretCallback function that accepts header argument', function() {
var secret = 'shhhhhh';
var secretCallback = function(req, headers, payload, cb) {
assert.equal(headers.alg, 'HS256');
assert.equal(payload.foo, 'bar');
process.nextTick(function() { return cb(null, secret); });
};
var token = jwt.sign({ foo: 'bar' }, secret);
req.headers = {};
req.headers.authorization = 'Bearer ' + token;
restifyjwt({ secret: secretCallback })(req, res, function() {
assert.equal('bar', req.user.foo);
});
});
});