Added support for subject and jwt id

This commit is contained in:
TAT
2015-06-26 20:43:04 +02:00
parent 33b326fb1d
commit ab76ec5bc5
3 changed files with 100 additions and 1 deletions
+21 -1
View File
@@ -29,13 +29,15 @@ encoded private key for RSA and ECDSA.
* `audience`
* `subject`
* `issuer`
* `jwtid`
* `subject`
* `noTimestamp`
* `headers`
If `payload` is not a buffer or a string, it will be coerced into a string
using `JSON.stringify`.
If any `expiresInMinutes`, `audience`, `subject`, `issuer` are not provided, there is no default. The jwt generated won't include those properties in the payload.
If any `expiresInMinutes`, `audience`, `subject`, `issuer`, `jwtid`, `subject` are not provided, there is no default. The jwt generated won't include those properties in the payload.
Additional headers can be provided via the `headers` object.
@@ -60,6 +62,8 @@ var token = jwt.sign({ foo: 'bar' }, cert, { algorithm: 'RS256'});
* `ignoreExpiration`
* `audience`
* `issuer`
* `jwtid`
* `subject`
(Asynchronous) If a callback is supplied, function acts asynchronously. Callback passed the payload decoded if the signature (and optionally expiration, audience, issuer) are valid. If not, it will be passed the error.
@@ -77,6 +81,8 @@ encoded public key for RSA and ECDSA.
* `audience`: if you want to check audience (`aud`), provide a value here
* `issuer`: if you want to check issuer (`iss`), provide a value here
* `ignoreExpiration`: if `true` do not validate the expiration of the token.
* `jwtid`: if you want to check JWT ID (`jti`), provide a value here
* `subject`: if you want to check subject (`sub`), provide a value here
```js
// verify a token symmetric - synchronous
@@ -119,6 +125,18 @@ jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer' }, function(
// if issuer mismatch, err == invalid issuer
});
// verify jwt id
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid' }, function(err, decoded) {
// if jwt id mismatch, err == invalid jwt id
});
// verify subject
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid', subject: 'subject' }, function(err, decoded) {
// if subject mismatch, err == invalid subject
});
// alg mismatch
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { algorithms: ['RS256'] }, function (err, payload) {
@@ -188,6 +206,8 @@ Error object:
* 'invalid signature'
* 'jwt audience invalid. expected: [OPTIONS AUDIENCE]'
* 'jwt issuer invalid. expected: [OPTIONS ISSUER]'
* 'jwt id invalid. expected: [OPTIONS JWT ID]'
* 'jwt subject invalid. expected: [OPTIONS SUBJECT]'
```js
jwt.verify(token, 'shhhhh', function(err, decoded) {
+13
View File
@@ -71,6 +71,9 @@ module.exports.sign = function(payload, secretOrPrivateKey, options) {
if (options.subject)
payload.sub = options.subject;
if (options.jwtid)
payload.jti = options.jwtid;
var encoding = 'utf8';
if (options.encoding) {
encoding = options.encoding;
@@ -188,5 +191,15 @@ module.exports.verify = function(jwtString, secretOrPublicKey, options, callback
return done(new JsonWebTokenError('jwt issuer invalid. expected: ' + options.issuer));
}
if (options.subject) {
if (payload.sub !== options.subject)
return done(new JsonWebTokenError('jwt subject invalid. expected: ' + options.subject));
}
if (options.jwtid) {
if (payload.jti !== options.jwtid)
return done(new JsonWebTokenError('jwt id invalid. expected: ' + options.jwtid));
}
return done(null, payload);
};
+66
View File
@@ -236,6 +236,72 @@ describe('RS256', function() {
});
});
describe('when signing a token with subject', function() {
var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', subject: 'subject' });
it('should check subject', function() {
jwt.verify(token, pub, { subject: 'subject' }, function(err, decoded) {
assert.isNotNull(decoded);
assert.isNull(err);
});
});
it('should throw when invalid subject', function() {
jwt.verify(token, pub, { issuer: 'wrongSubject' }, function(err, decoded) {
assert.isUndefined(decoded);
assert.isNotNull(err);
assert.equal(err.name, 'JsonWebTokenError');
assert.instanceOf(err, jwt.JsonWebTokenError);
});
});
});
describe('when signing a token without subject', function() {
var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' });
it('should check subject', function() {
jwt.verify(token, pub, { subject: 'subject' }, function(err, decoded) {
assert.isUndefined(decoded);
assert.isNotNull(err);
assert.equal(err.name, 'JsonWebTokenError');
assert.instanceOf(err, jwt.JsonWebTokenError);
});
});
});
describe('when signing a token with jwt id', function() {
var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', jwtid: 'jwtid' });
it('should check jwt id', function() {
jwt.verify(token, pub, { jwtid: 'jwtid' }, function(err, decoded) {
assert.isNotNull(decoded);
assert.isNull(err);
});
});
it('should throw when invalid jwt id', function() {
jwt.verify(token, pub, { jwtid: 'wrongJwtid' }, function(err, decoded) {
assert.isUndefined(decoded);
assert.isNotNull(err);
assert.equal(err.name, 'JsonWebTokenError');
assert.instanceOf(err, jwt.JsonWebTokenError);
});
});
});
describe('when signing a token without jwt id', function() {
var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' });
it('should check jwt id', function() {
jwt.verify(token, pub, { jwtid: 'jwtid' }, function(err, decoded) {
assert.isUndefined(decoded);
assert.isNotNull(err);
assert.equal(err.name, 'JsonWebTokenError');
assert.instanceOf(err, jwt.JsonWebTokenError);
});
});
});
describe('when verifying a malformed token', function() {
it('should throw', function(done) {
jwt.verify('fruit.fruit.fruit', pub, function(err, decoded) {