Skip to content

Commit

Permalink
add verify option maxAge (with tests)
Browse files Browse the repository at this point in the history
  • Loading branch information
junosuarez committed Jul 16, 2015
1 parent d7c5793 commit 49d54e5
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 11 deletions.
12 changes: 11 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var JWT = module.exports;

var JsonWebTokenError = JWT.JsonWebTokenError = require('./lib/JsonWebTokenError');
var TokenExpiredError = JWT.TokenExpiredError = require('./lib/TokenExpiredError');

var ms = require('ms')

JWT.decode = function (jwt, options) {
options = options || {};
Expand Down Expand Up @@ -195,5 +195,15 @@ JWT.verify = function(jwtString, secretOrPublicKey, options, callback) {
return done(new JsonWebTokenError('jwt issuer invalid. expected: ' + options.issuer));
}

if (options.maxAge) {
var maxAge = ms(options.maxAge);
if (typeof payload.iat !== 'number') {
return done(new JsonWebTokenError('iat required when maxAge is specified'));
}
if (Date.now() - (payload.iat * 1000) > maxAge) {
return done(new TokenExpiredError('maxAge exceded', new Date(payload.iat * 1000 + maxAge)));
}
}

return done(null, payload);
};
86 changes: 76 additions & 10 deletions test/verify.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,20 @@ describe('verify', function() {
});

describe('expiration', function () {
// { foo: 'bar', iat: 1437018582, exp: 1437018583 }
var token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE0MzcwMTg1ODIsImV4cCI6MTQzNzAxODU4M30.NmMv7sXjM1dW0eALNXud8LoXknZ0mH14GtnFclwJv0s';
var key = 'key';

var clock;
beforeEach(function () {
// clock = sinon.useFakeTimers(1437018650768);
});
afterEach(function () {
try { clock.restore(); } catch (e) {}
});

it('should error on expired token', function (done) {
clock = sinon.useFakeTimers(1437018650768);
var token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE0MzcwMTg1ODIsImV4cCI6MTQzNzAxODU4M30.NmMv7sXjM1dW0eALNXud8LoXknZ0mH14GtnFclwJv0s';
var key = 'key';
jwt.verify(token, key, {algorithms: ['HS256']}, function (err, p) {
clock = sinon.useFakeTimers(1437018650000);
var options = {algorithms: ['HS256']};

jwt.verify(token, key, options, function (err, p) {
assert.equal(err.name, 'TokenExpiredError');
assert.equal(err.message, 'jwt expired');
assert.equal(err.expiredAt.constructor.name, 'Date');
Expand All @@ -53,14 +54,79 @@ describe('verify', function() {

it('should not error on unexpired token', function (done) {
clock = sinon.useFakeTimers(1437018582000);
var token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE0MzcwMTg1ODIsImV4cCI6MTQzNzAxODU4M30.NmMv7sXjM1dW0eALNXud8LoXknZ0mH14GtnFclwJv0s';
var key = 'key';
jwt.verify(token, key, {algorithms: ['HS256']}, function (err, p) {
var options = {algorithms: ['HS256']}

jwt.verify(token, key, options, function (err, p) {
assert.isNull(err);
assert.equal(p.foo, 'bar');
done();
});
});

describe('option: maxAge', function () {
it('should error for claims issued before a certain timespan', function (done) {
clock = sinon.useFakeTimers(1437018582500);
var options = {algorithms: ['HS256'], maxAge: '321ms'};

jwt.verify(token, key, options, function (err, p) {
assert.equal(err.name, 'TokenExpiredError');
assert.equal(err.message, 'maxAge exceded');
assert.equal(err.expiredAt.constructor.name, 'Date');
assert.equal(Number(err.expiredAt), 1437018582321);
assert.isUndefined(p);
done();
});
});
it('should not error if within maxAge timespan', function (done) {
clock = sinon.useFakeTimers(1437018582500);
var options = {algorithms: ['HS256'], maxAge: '600ms'};

jwt.verify(token, key, options, function (err, p) {
assert.isNull(err);
assert.equal(p.foo, 'bar');
done();
});
});
it('can be more restrictive than expiration', function (done) {
clock = sinon.useFakeTimers(1437018582900);
var options = {algorithms: ['HS256'], maxAge: '800ms'};

jwt.verify(token, key, options, function (err, p) {
assert.equal(err.name, 'TokenExpiredError');
assert.equal(err.message, 'maxAge exceded');
assert.equal(err.expiredAt.constructor.name, 'Date');
assert.equal(Number(err.expiredAt), 1437018582800);
assert.isUndefined(p);
done();
});
});
it('cannot be more permissive than expiration', function (done) {
clock = sinon.useFakeTimers(1437018583100);
var options = {algorithms: ['HS256'], maxAge: '1200ms'};

jwt.verify(token, key, options, function (err, p) {
// maxAge not exceded, but still expired
assert.equal(err.name, 'TokenExpiredError');
assert.equal(err.message, 'jwt expired');
assert.equal(err.expiredAt.constructor.name, 'Date');
assert.equal(Number(err.expiredAt), 1437018583000);
assert.isUndefined(p);
done();
});
});
it('should error if maxAge is specified but there is no iat claim', function (done) {
clock = sinon.useFakeTimers(1437018582900);
var token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIifQ.0MBPd4Bru9-fK_HY3xmuDAc6N_embknmNuhdb9bKL_U';
var options = {algorithms: ['HS256'], maxAge: '1s'};

jwt.verify(token, key, options, function (err, p) {
assert.equal(err.name, 'JsonWebTokenError');
assert.equal(err.message, 'iat required when maxAge is specified');
assert.isUndefined(p);
done();
});
});
});
});

});

0 comments on commit 49d54e5

Please sign in to comment.