Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: auth0/node-jsonwebtoken
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.2.2
Choose a base ref
...
head repository: auth0/node-jsonwebtoken
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v5.0.0
Choose a head ref
  • 10 commits
  • 6 files changed
  • 2 contributors

Commits on Apr 6, 2015

  1. Copy the full SHA
    a77df6d View commit details
  2. Update CHANGELOG.md

    pose committed Apr 6, 2015
    Copy the full SHA
    24a3700 View commit details
  3. Update CHANGELOG.md

    pose committed Apr 6, 2015
    Copy the full SHA
    954bd7a View commit details

Commits on Apr 7, 2015

  1. Only set iat if there is none

    Makes sense?
    dschenkelman committed Apr 7, 2015
    Copy the full SHA
    35036b1 View commit details

Commits on Apr 10, 2015

  1. Updating to jws@^3.0.0

    As `jws@3.0.0` changed the verify method signature to be `jws.verify(signature, algorithm, secretOrKey)`, the token header must be decoded first in order to make sure that the `alg` field matches one of the allowed `options.algorithms`. After that, the now validated `header.alg` is passed to `jws.verify`
    
    As the order of steps has changed, the error that was thrown when the JWT was invalid is no longer the `jws` one:
    
    { [Error: Invalid token: no header in signature 'a.b.c'] code: 'MISSING_HEADER', signature: 'a.b.c' }
    
    That old error (removed from jws) has been replaced by a `JsonWebTokenError` with message `invalid token`. That's why this change will bump be a major.
    pose committed Apr 10, 2015
    Copy the full SHA
    1e46234 View commit details
  2. Adding @dschenkelman feedback.

    pose committed Apr 10, 2015
    Copy the full SHA
    19e6cc6 View commit details
  3. Renaming header.alg mismatch exception to invalid algorithm and a…

    …dding more mismatch tests.
    pose committed Apr 10, 2015
    Copy the full SHA
    9f24ffd View commit details
  4. Merge pull request #78 from auth0/update-to-jws-3

    Update to jws@^3.0.0
    dschenkelman committed Apr 10, 2015
    Copy the full SHA
    634b8ed View commit details
  5. Merge pull request #75 from auth0/dschenkelman-patch-1

    Only set iat if there is none
    pose committed Apr 10, 2015
    Copy the full SHA
    e900282 View commit details
  6. 5.0.0

    pose committed Apr 10, 2015
    Copy the full SHA
    db8fb93 View commit details
Showing with 83 additions and 22 deletions.
  1. +26 −1 CHANGELOG.md
  2. +7 −0 README.md
  3. +16 −9 index.js
  4. +5 −5 package.json
  5. +1 −1 test/jwt.rs.tests.js
  6. +28 −6 test/wrong_alg.tests.js
27 changes: 26 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -3,6 +3,31 @@
All notable changes to this project will be documented in this file starting from version **v4.0.0**.
This project adheres to [Semantic Versioning](http://semver.org/).

## [4.2.2] - 2015-03-26
### Fixed

- [asymmetric-keys] Fix verify for RSAPublicKey formated keys (`jfromaniello - awlayton`)
https://github.com/auth0/node-jsonwebtoken/commit/402794663b9521bf602fcc6f2e811e7d3912f9dc
https://github.com/auth0/node-jsonwebtoken/commit/8df6aabbc7e1114c8fb3917931078254eb52c222

## [4.2.1] - 2015-03-17
### Fixed

- [asymmetric-keys] Fixed issue when public key starts with BEING PUBLIC KEY (https://github.com/auth0/node-jsonwebtoken/issues/70) (`jfromaniello`)
https://github.com/auth0/node-jsonwebtoken/commit/7017e74db9b194448ff488b3e16468ada60c4ee5

## [4.2.0] - 2015-03-16
### Security

- [asymmetric-keys] Making sure a token signed with an asymmetric key will be verified using a asymmetric key.
When the verification part was expecting a token digitally signed with an asymmetric key (RS/ES family) of algorithms an attacker could send a token signed with a symmetric algorithm (HS* family).

The issue was caused because the same signature was used to verify both type of tokens (`verify` method parameter: `secretOrPublicKey`).

This change adds a new parameter to the verify called `algorithms`. This can be used to specify a list of supported algorithms, but the default value depends on the secret used: if the secretOrPublicKey contains the string `BEGIN CERTIFICATE` the default is `[ 'RS256','RS384','RS512','ES256','ES384','ES512' ]` otherwise is `[ 'HS256','HS384','HS512' ]`. (`jfromaniello`)
https://github.com/auth0/node-jsonwebtoken/commit/c2bf7b2cd7e8daf66298c2d168a008690bc4bdd3
https://github.com/auth0/node-jsonwebtoken/commit/1bb584bc382295eeb7ee8c4452a673a77a68b687

## [4.1.0] - 2015-03-10
### Changed
- Assume the payload is JSON even when there is no `typ` property. [5290db1](https://github.com/auth0/node-jsonwebtoken/commit/5290db1bd74f74cd38c90b19e2355ef223a4d931)
@@ -17,4 +42,4 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
- Fix wrong error message when the audience doesn't match. [44e3c8d](https://github.com/auth0/node-jsonwebtoken/commit/44e3c8d757e6b4e2a57a69a035f26b4abec3e327)
- Fix wrong error message when the issuer doesn't match. [44e3c8d](https://github.com/auth0/node-jsonwebtoken/commit/44e3c8d757e6b4e2a57a69a035f26b4abec3e327)
- Fix wrong `iat` and `exp` values when signing with `noTimestamp`. [331b7bc](https://github.com/auth0/node-jsonwebtoken/commit/331b7bc9cc335561f8806f2c4558e105cb53e0a6)
- Fix wrong `iat` and `exp` values when signing with `noTimestamp`. [331b7bc](https://github.com/auth0/node-jsonwebtoken/commit/331b7bc9cc335561f8806f2c4558e105cb53e0a6)
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -75,6 +75,7 @@ encoded public key for RSA and ECDSA.

`options`

* `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
* `issuer`: if you want to check issuer (`iss`), provide a value here

@@ -119,6 +120,12 @@ jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer' }, function(
// if issuer mismatch, err == invalid issuer
});

// alg mismatch
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { algorithms: ['RS256'] }, function (err, payload) {
// if token alg != RS256, err == invalid signature
});

```

### jwt.decode(token [, options])
25 changes: 16 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ module.exports.sign = function(payload, secretOrPrivateKey, options) {

var timestamp = Math.floor(Date.now() / 1000);
if (!options.noTimestamp) {
payload.iat = timestamp;
payload.iat = payload.iat || timestamp;
}

var expiresInSeconds = options.expiresInMinutes ?
@@ -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'));
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jsonwebtoken",
"version": "4.2.2",
"version": "5.0.0",
"description": "JSON Web Token implementation (symmetric and asymmetric)",
"main": "index.js",
"scripts": {
@@ -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"
2 changes: 1 addition & 1 deletion test/jwt.rs.tests.js
Original file line number Diff line number Diff line change
@@ -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();
});
});
34 changes: 28 additions & 6 deletions test/wrong_alg.tests.js
Original file line number Diff line number Diff line change
@@ -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/);
});
});
});

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/);
});
});


});