diff --git a/index.js b/index.js index 1c04474..420cb64 100644 --- a/index.js +++ b/index.js @@ -112,15 +112,27 @@ module.exports.verify = function(jwtString, secretOrPublicKey, options, callback ~secretOrPublicKey.toString().indexOf('BEGIN PUBLIC KEY') ? [ 'RS256','RS384','RS512','ES256','ES384','ES512' ] : ~secretOrPublicKey.toString().indexOf('BEGIN RSA PUBLIC KEY') ? - [ 'RS256','RS384','RS512' ] : - [ 'HS256','HS384','HS512' ]; + [ 'RS256','RS384','RS512' ] : + [ 'HS256','HS384','HS512' ]; } + var decodedToken = jws.decode(jwtString); + + if (!decodedToken) { + return done(new JsonWebTokenError('invalid token')); + } + + var header = decodedToken.header; + + if (!~options.algorithms.indexOf(header.alg)) { + return done(new JsonWebTokenError('invalid algorithm')); + } + var valid; try { - valid = jws.verify(jwtString, secretOrPublicKey); + valid = jws.verify(jwtString, header.alg, secretOrPublicKey); } catch (e) { return done(e); } @@ -136,11 +148,6 @@ module.exports.verify = function(jwtString, secretOrPublicKey, options, callback return done(err); } - var header = jws.decode(jwtString).header; - if (!~options.algorithms.indexOf(header.alg)) { - return done(new JsonWebTokenError('invalid signature')); - } - if (typeof payload.exp !== 'undefined' && !options.ignoreExpiration) { if (typeof payload.exp !== 'number') { return done(new JsonWebTokenError('invalid exp value')); diff --git a/package.json b/package.json index ceb68ca..af726bf 100644 --- a/package.json +++ b/package.json @@ -19,12 +19,12 @@ "url": "https://github.com/auth0/node-jsonwebtoken/issues" }, "dependencies": { - "jws": "~2.0.0" + "jws": "^3.0.0" }, "devDependencies": { - "atob": "~1.1.2", - "chai": "~1.10.0", - "mocha": "~2.1.0" + "atob": "^1.1.2", + "chai": "^1.10.0", + "mocha": "^2.1.0" }, "engines": { "npm": ">=1.4.28" diff --git a/test/jwt.rs.tests.js b/test/jwt.rs.tests.js index a7d6578..f053fd7 100644 --- a/test/jwt.rs.tests.js +++ b/test/jwt.rs.tests.js @@ -241,7 +241,7 @@ describe('RS256', function() { jwt.verify('fruit.fruit.fruit', pub, function(err, decoded) { assert.isUndefined(decoded); assert.isNotNull(err); - assert.equal(err.name, 'Error'); + assert.equal(err.name, 'JsonWebTokenError'); done(); }); }); diff --git a/test/wrong_alg.tests.js b/test/wrong_alg.tests.js index 513ba18..04ce48e 100644 --- a/test/wrong_alg.tests.js +++ b/test/wrong_alg.tests.js @@ -11,10 +11,32 @@ var pub = fs.readFileSync(path.join(__dirname, 'pub.pem'), 'utf8'); var TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE0MjY1NDY5MTl9.ETgkTn8BaxIX4YqvUWVFPmum3moNZ7oARZtSBXb_vP4'; -describe('signing with pub key as symmetric', function () { - it('should not verify', function () { - expect(function () { - jwt.verify(TOKEN, pub); - }).to.throw(JsonWebTokenError, /invalid signature/); +describe('when setting a wrong `header.alg`', function () { + + describe('signing with pub key as symmetric', function () { + it('should not verify', function () { + expect(function () { + jwt.verify(TOKEN, pub); + }).to.throw(JsonWebTokenError, /invalid algorithm/); + }); + }); + + describe('signing with pub key as HS256 and whitelisting only RS256', function () { + it('should not verify', function () { + expect(function () { + jwt.verify(TOKEN, pub, {algorithms: ['RS256']}); + }).to.throw(JsonWebTokenError, /invalid algorithm/); + }); }); -}); \ No newline at end of file + + describe('signing with HS256 and checking with HS384', function () { + it('should not verify', function () { + expect(function () { + var token = jwt.sign({foo: 'bar'}, 'secret', {algorithm: 'HS256'}); + jwt.verify(token, 'some secret', {algorithms: ['HS384']}); + }).to.throw(JsonWebTokenError, /invalid algorithm/); + }); + }); + + +});