Skip to content

Commit d5e9696

Browse files
committed
feat: add options.type
1 parent bc28861 commit d5e9696

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ As mentioned in [this comment](https://github.com/auth0/node-jsonwebtoken/issues
147147
> * rsa - ['RS256', 'RS384', 'RS512']
148148
> * ec - ['ES256', 'ES384', 'ES512']
149149
> * default - ['RS256', 'RS384', 'RS512']
150+
* `type`: if you want to check token type (`typ`), provide a string value here (e.g. 'JWT', 'at+jwt').
150151
* `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.
151152
> Eg: `"urn:foo"`, `/urn:f[o]{2}/`, `[/urn:f[o]{2}/, "urn:bar"]`
152153
* `complete`: return an object with the decoded `{ payload, header, signature }` instead of only the usual content of the payload.
@@ -191,6 +192,12 @@ jwt.verify(token, cert, function(err, decoded) {
191192
console.log(decoded.foo) // bar
192193
});
193194

195+
// verify type
196+
var cert = fs.readFileSync('public.pem'); // get public key
197+
jwt.verify(token, cert, { type: 'at+jwt' }, function(err, decoded) {
198+
// if typ mismatch, err == invalid type
199+
});
200+
194201
// verify audience
195202
var cert = fs.readFileSync('public.pem'); // get public key
196203
jwt.verify(token, cert, { audience: 'urn:foo' }, function(err, decoded) {
@@ -314,6 +321,8 @@ Error object:
314321
* 'jwt issuer invalid. expected: [OPTIONS ISSUER]'
315322
* 'jwt id invalid. expected: [OPTIONS JWT ID]'
316323
* 'jwt subject invalid. expected: [OPTIONS SUBJECT]'
324+
* 'jwt type invalid. expected: [OPTIONS TYPE]'
325+
317326

318327
```js
319328
jwt.verify(token, 'shhhhh', function(err, decoded) {

test/option-complete.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe('complete option', function () {
1010
const secret = fs.readFileSync(path.join(__dirname, 'priv.pem'));
1111
const pub = fs.readFileSync(path.join(__dirname, 'pub.pem'));
1212

13-
const header = { alg: 'RS256' };
13+
const header = { alg: 'RS256', typ: 'JWT' };
1414
const payload = { iat: Math.floor(Date.now() / 1000 ) };
1515
const signed = jws.sign({ header, payload, secret, encoding: 'utf8' });
1616
const signature = jws.decode(signed).signature;
@@ -26,6 +26,7 @@ describe('complete option', function () {
2626
testUtils.asyncCheck(done, () => {
2727
expect(err).to.be.null;
2828
expect(decoded.header).to.have.property('alg', header.alg);
29+
expect(decoded.header).to.have.property('typ', header.typ);
2930
expect(decoded.payload).to.have.property('iat', payload.iat);
3031
expect(decoded).to.have.property('signature', signature);
3132
});

test/verify.tests.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,32 @@ describe('verify', function() {
268268
});
269269
});
270270

271+
describe('option: type', function () {
272+
// { "alg": "HS256", "typ": "JWT" } { "foo": "bar", "iat": 1437018582, "exp": 1437018592 }
273+
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE0MzcwMTg1ODIsImV4cCI6MTQzNzAxODU5Mn0.3aR3vocmgRpG05rsI9MpR6z2T_BGtMQaPq2YR6QaroU';
274+
let clock;
275+
const key = 'key';
276+
277+
beforeEach(function () {
278+
// iat + 1s
279+
try { clock = sinon.useFakeTimers(1437018583000); } catch (e) {}
280+
});
281+
282+
afterEach(function () {
283+
try { clock.restore(); } catch (e) {}
284+
});
285+
286+
it('should pass if token.header.typ is equal to options.type', function () {
287+
const options = { type: 'JWT' };
288+
expect(function() { jwt.verify(token, key, options) }).to.not.throw();
289+
});
290+
291+
it('should error if token.header.typ is not equal to options.type', function () {
292+
const options = { type: 'at+jwt' };
293+
expect(function() { jwt.verify(token, key, options) }).to.throw('jwt type invalid. expected: at+jwt');
294+
});
295+
});
296+
271297
describe('when verifying a token with an unsupported public key type', function () {
272298
it('should throw an error', function() {
273299
const token = 'eyJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE2Njk5OTAwMDN9.YdjFWJtPg_9nccMnTfQyesWQ0UX-GsWrfCGit_HqjeIkNjoV6dkAJ8AtbnVEhA4oxwqSXx6ilMOfHEjmMlPtyyyVKkWKQHcIWYnqPbNSEv8a7Men8KhJTIWb4sf5YbhgSCpNvU_VIZjLO1Z0PzzgmEikp0vYbxZFAbCAlZCvUlcIc-kdjIRCnDJe0BBrYRxNLEJtYsf7D1yFIFIqw8-VP87yZdExA4eHsTaE84SgnL24ZK5h5UooDx-IRNd_rrMyio8kNy63grVxCWOtkXZ26iZk6v-HMsnBqxvUwR6-8wfaWrcpADkyUO1q3SNsoTdwtflbvfwgjo3uve0IvIzHMw';

verify.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ module.exports = function (jwtString, secretOrPublicKey, options, callback) {
8383
}
8484

8585
const header = decodedToken.header;
86+
87+
if (options.type) {
88+
const invalid_type =
89+
(typeof options.type === 'string' && header.typ !== options.type);
90+
91+
if (invalid_type) {
92+
return done(new JsonWebTokenError('jwt type invalid. expected: ' + options.type));
93+
}
94+
}
95+
8696
let getSecret;
8797

8898
if(typeof secretOrPublicKey === 'function') {

0 commit comments

Comments
 (0)