Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ As mentioned in [this comment](https://github.com/auth0/node-jsonwebtoken/issues
> * rsa - ['RS256', 'RS384', 'RS512']
> * ec - ['ES256', 'ES384', 'ES512']
> * default - ['RS256', 'RS384', 'RS512']
* `type`: if you want to check token type (`typ`), provide a string value here (e.g. 'JWT', 'at+jwt').
* `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, header, signature }` instead of only the usual content of the payload.
Expand Down Expand Up @@ -191,6 +192,12 @@ jwt.verify(token, cert, function(err, decoded) {
console.log(decoded.foo) // bar
});

// verify type
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { type: 'at+jwt' }, function(err, decoded) {
// if typ mismatch, err == invalid type
});

// verify audience
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { audience: 'urn:foo' }, function(err, decoded) {
Expand Down Expand Up @@ -314,6 +321,8 @@ Error object:
* 'jwt issuer invalid. expected: [OPTIONS ISSUER]'
* 'jwt id invalid. expected: [OPTIONS JWT ID]'
* 'jwt subject invalid. expected: [OPTIONS SUBJECT]'
* 'jwt type invalid. expected: [OPTIONS TYPE]'


```js
jwt.verify(token, 'shhhhh', function(err, decoded) {
Expand Down
3 changes: 2 additions & 1 deletion test/option-complete.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ 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 header = { alg: 'RS256', typ: 'JWT' };
const payload = { iat: Math.floor(Date.now() / 1000 ) };
const signed = jws.sign({ header, payload, secret, encoding: 'utf8' });
const signature = jws.decode(signed).signature;
Expand All @@ -26,6 +26,7 @@ describe('complete option', function () {
testUtils.asyncCheck(done, () => {
expect(err).to.be.null;
expect(decoded.header).to.have.property('alg', header.alg);
expect(decoded.header).to.have.property('typ', header.typ);
expect(decoded.payload).to.have.property('iat', payload.iat);
expect(decoded).to.have.property('signature', signature);
});
Expand Down
26 changes: 26 additions & 0 deletions test/verify.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,32 @@ describe('verify', function() {
});
});

describe('option: type', function () {
// { "alg": "HS256", "typ": "JWT" } { "foo": "bar", "iat": 1437018582, "exp": 1437018592 }
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE0MzcwMTg1ODIsImV4cCI6MTQzNzAxODU5Mn0.3aR3vocmgRpG05rsI9MpR6z2T_BGtMQaPq2YR6QaroU';
let clock;
const key = 'key';

beforeEach(function () {
// iat + 1s
try { clock = sinon.useFakeTimers(1437018583000); } catch (e) {}
});

afterEach(function () {
try { clock.restore(); } catch (e) {}
});

it('should pass if token.header.typ is equal to options.type', function () {
const options = { type: 'JWT' };
expect(function() { jwt.verify(token, key, options) }).to.not.throw();
});

it('should error if token.header.typ is not equal to options.type', function () {
const options = { type: 'at+jwt' };
expect(function() { jwt.verify(token, key, options) }).to.throw('jwt type invalid. expected: at+jwt');
});
});

describe('when verifying a token with an unsupported public key type', function () {
it('should throw an error', function() {
const token = 'eyJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE2Njk5OTAwMDN9.YdjFWJtPg_9nccMnTfQyesWQ0UX-GsWrfCGit_HqjeIkNjoV6dkAJ8AtbnVEhA4oxwqSXx6ilMOfHEjmMlPtyyyVKkWKQHcIWYnqPbNSEv8a7Men8KhJTIWb4sf5YbhgSCpNvU_VIZjLO1Z0PzzgmEikp0vYbxZFAbCAlZCvUlcIc-kdjIRCnDJe0BBrYRxNLEJtYsf7D1yFIFIqw8-VP87yZdExA4eHsTaE84SgnL24ZK5h5UooDx-IRNd_rrMyio8kNy63grVxCWOtkXZ26iZk6v-HMsnBqxvUwR6-8wfaWrcpADkyUO1q3SNsoTdwtflbvfwgjo3uve0IvIzHMw';
Expand Down
10 changes: 10 additions & 0 deletions verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ module.exports = function (jwtString, secretOrPublicKey, options, callback) {
}

const header = decodedToken.header;

if (options.type) {
const invalid_type =
(typeof options.type === 'string' && header.typ !== options.type);

if (invalid_type) {
return done(new JsonWebTokenError('jwt type invalid. expected: ' + options.type));
}
}

let getSecret;

if(typeof secretOrPublicKey === 'function') {
Expand Down