From 5e8d01342a4288ff44af0fc0bb6e0a9dbe7cee79 Mon Sep 17 00:00:00 2001 From: Javier Espinosa Date: Tue, 11 Sep 2018 20:23:26 +0200 Subject: [PATCH 1/4] Add complete option in verify --- README.md | 1 + test/verify.tests.js | 24 ++++++++++++++++++++++++ verify.js | 13 +++++++++++++ 3 files changed, 38 insertions(+) diff --git a/README.md b/README.md index f8a2d2c..a66fae2 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ As mentioned in [this comment](https://github.com/auth0/node-jsonwebtoken/issues * `algorithms`: List of strings with the names of the allowed algorithms. For instance, `["HS256", "HS384"]`. * `audience`: if you want to check audience (`aud`), provide a value here. The audience can be checked against a string, a regular expression or a list of strings and/or regular expressions. Eg: `"urn:foo"`, `/urn:f[o]{2}/`, `[/urn:f[o]{2}/, "urn:bar"]` +* `complete`: return an object with the decoded payload and header * `issuer` (optional): string or array of strings of valid values for the `iss` field. * `ignoreExpiration`: if `true` do not validate the expiration of the token. * `ignoreNotBefore`... diff --git a/test/verify.tests.js b/test/verify.tests.js index 29bbe10..fd122ab 100644 --- a/test/verify.tests.js +++ b/test/verify.tests.js @@ -69,6 +69,30 @@ describe('verify', function() { }); }); + describe('option: complete', function() { + it('should return header, payload and signature', function (done) { + var header = { alg: 'RS256' }; + var payload = { iat: Math.floor(Date.now() / 1000 ) }; + + var signed = jws.sign({ + header: header, + payload: payload, + secret: priv, + encoding: 'utf8' + }); + + var signature = jws.decode(signed).signature; + + jwt.verify(signed, pub, {typ: 'JWT', complete: true}, function(err, p) { + assert.isNull(err); + assert.deepEqual(p.header, header); + assert.deepEqual(p.payload, payload); + assert.deepEqual(p.signature, signature); + done(); + }); + }); + }); + describe('secret or token as callback', function () { var token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE0MzcwMTg1ODIsImV4cCI6MTQzNzAxODU5Mn0.3aR3vocmgRpG05rsI9MpR6z2T_BGtMQaPq2YR6QaroU'; var key = 'key'; diff --git a/verify.js b/verify.js index e730e2a..2c443ef 100644 --- a/verify.js +++ b/verify.js @@ -193,6 +193,19 @@ module.exports = function (jwtString, secretOrPublicKey, options, callback) { } } + //return header if `complete` option is enabled. header includes claims + //such as `kid` and `alg` used to select the key within a JWKS needed to + //verify the signature + if (options.complete === true) { + var signature = decodedToken.signature; + + return done(null, { + header: header, + payload: payload, + signature: signature + }); + } + return done(null, payload); }); }; From 3753d99eacdb37ef08233a3b2d7241a98a5f556b Mon Sep 17 00:00:00 2001 From: Javier Espinosa Date: Wed, 13 Feb 2019 21:46:32 +0100 Subject: [PATCH 2/4] Remove comment --- verify.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/verify.js b/verify.js index 3a45614..6b459c7 100644 --- a/verify.js +++ b/verify.js @@ -203,9 +203,6 @@ module.exports = function (jwtString, secretOrPublicKey, options, callback) { } } - //return header if `complete` option is enabled. header includes claims - //such as `kid` and `alg` used to select the key within a JWKS needed to - //verify the signature if (options.complete === true) { var signature = decodedToken.signature; From fdc1f043cf6e2c221a10a07602fcc4746cd215f3 Mon Sep 17 00:00:00 2001 From: Eduardo Diaz Date: Sat, 16 Feb 2019 14:05:07 +0100 Subject: [PATCH 3/4] Update README.md Co-Authored-By: javespi --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2315d2f..4bdeec0 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ As mentioned in [this comment](https://github.com/auth0/node-jsonwebtoken/issues * `algorithms`: List of strings with the names of the allowed algorithms. For instance, `["HS256", "HS384"]`. * `audience`: if you want to check audience (`aud`), provide a value here. The audience can be checked against a string, a regular expression or a list of strings and/or regular expressions. > Eg: `"urn:foo"`, `/urn:f[o]{2}/`, `[/urn:f[o]{2}/, "urn:bar"]` -* `complete`: return an object with the decoded payload and header +* `complete`: return an object with the decoded `{ payload, header, signature }` instead of only the usual content of the payload. * `issuer` (optional): string or array of strings of valid values for the `iss` field. * `ignoreExpiration`: if `true` do not validate the expiration of the token. * `ignoreNotBefore`... From 4d8f50af92b12b287f04f00e0c71dd2929ce5ba4 Mon Sep 17 00:00:00 2001 From: Javier Espinosa Date: Sat, 16 Feb 2019 19:53:28 +0100 Subject: [PATCH 4/4] Move tests in a specific file --- test/option-complete.test.js | 53 ++++++++++++++++++++++++++++++++++++ test/verify.tests.js | 24 ---------------- 2 files changed, 53 insertions(+), 24 deletions(-) create mode 100644 test/option-complete.test.js diff --git a/test/option-complete.test.js b/test/option-complete.test.js new file mode 100644 index 0000000..29320e8 --- /dev/null +++ b/test/option-complete.test.js @@ -0,0 +1,53 @@ +'use strict'; + +const jws = require('jws'); +const expect = require('chai').expect; +const path = require('path'); +const fs = require('fs'); +const testUtils = require('./test-utils') + +describe('complete option', function () { + const secret = fs.readFileSync(path.join(__dirname, 'priv.pem')); + const pub = fs.readFileSync(path.join(__dirname, 'pub.pem')); + + const header = { alg: 'RS256' }; + const payload = { iat: Math.floor(Date.now() / 1000 ) }; + const signed = jws.sign({ header, payload, secret, encoding: 'utf8' }); + const signature = jws.decode(signed).signature; + + [ + { + description: 'should return header, payload and signature', + complete: true, + }, + ].forEach((testCase) => { + it(testCase.description, function (done) { + testUtils.verifyJWTHelper(signed, pub, { typ: 'JWT', complete: testCase.complete }, (err, decoded) => { + testUtils.asyncCheck(done, () => { + expect(err).to.be.null; + expect(decoded.header).to.have.property('alg', header.alg); + expect(decoded.payload).to.have.property('iat', payload.iat); + expect(decoded).to.have.property('signature', signature); + }); + }); + }); + }); + [ + { + description: 'should return payload', + complete: false, + }, + ].forEach((testCase) => { + it(testCase.description, function (done) { + testUtils.verifyJWTHelper(signed, pub, { typ: 'JWT', complete: testCase.complete }, (err, decoded) => { + testUtils.asyncCheck(done, () => { + expect(err).to.be.null; + expect(decoded.header).to.be.undefined; + expect(decoded.payload).to.be.undefined; + expect(decoded.signature).to.be.undefined; + expect(decoded).to.have.property('iat', payload.iat); + }); + }); + }); + }); +}); diff --git a/test/verify.tests.js b/test/verify.tests.js index fd122ab..29bbe10 100644 --- a/test/verify.tests.js +++ b/test/verify.tests.js @@ -69,30 +69,6 @@ describe('verify', function() { }); }); - describe('option: complete', function() { - it('should return header, payload and signature', function (done) { - var header = { alg: 'RS256' }; - var payload = { iat: Math.floor(Date.now() / 1000 ) }; - - var signed = jws.sign({ - header: header, - payload: payload, - secret: priv, - encoding: 'utf8' - }); - - var signature = jws.decode(signed).signature; - - jwt.verify(signed, pub, {typ: 'JWT', complete: true}, function(err, p) { - assert.isNull(err); - assert.deepEqual(p.header, header); - assert.deepEqual(p.payload, payload); - assert.deepEqual(p.signature, signature); - done(); - }); - }); - }); - describe('secret or token as callback', function () { var token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE0MzcwMTg1ODIsImV4cCI6MTQzNzAxODU5Mn0.3aR3vocmgRpG05rsI9MpR6z2T_BGtMQaPq2YR6QaroU'; var key = 'key';