jsonwebtoken
Advanced tools
Comparing version 7.1.0 to 7.1.1
@@ -7,2 +7,7 @@ # Change Log | ||
## 7.1.1 - 2016-07-12 | ||
- do not mutate options in jwt.verify, closes #227 ([63263a28a268624dab0927b9ad86fffa44a10f84](https://github.com/auth0/node-jsonwebtoken/commit/63263a28a268624dab0927b9ad86fffa44a10f84)), closes [#227](https://github.com/auth0/node-jsonwebtoken/issues/227) | ||
- refactor into multiple files ([e11d505207fa33501298300c9accbfb809d8748d](https://github.com/auth0/node-jsonwebtoken/commit/e11d505207fa33501298300c9accbfb809d8748d)) | ||
## 7.1.0 - 2016-07-12 | ||
@@ -9,0 +14,0 @@ |
201
index.js
@@ -1,195 +0,8 @@ | ||
var jws = require('jws'); | ||
var ms = require('ms'); | ||
var JWT = module.exports; | ||
var JsonWebTokenError = JWT.JsonWebTokenError = require('./lib/JsonWebTokenError'); | ||
var NotBeforeError = module.exports.NotBeforeError = require('./lib/NotBeforeError'); | ||
var TokenExpiredError = JWT.TokenExpiredError = require('./lib/TokenExpiredError'); | ||
JWT.decode = function (jwt, options) { | ||
options = options || {}; | ||
var decoded = jws.decode(jwt, options); | ||
if (!decoded) { return null; } | ||
var payload = decoded.payload; | ||
//try parse the payload | ||
if(typeof payload === 'string') { | ||
try { | ||
var obj = JSON.parse(payload); | ||
if(typeof obj === 'object') { | ||
payload = obj; | ||
} | ||
} catch (e) { } | ||
} | ||
//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) { | ||
return { | ||
header: decoded.header, | ||
payload: payload, | ||
signature: decoded.signature | ||
}; | ||
} | ||
return payload; | ||
module.exports = { | ||
decode: require('./decode'), | ||
verify: require('./verify'), | ||
sign: require('./sign'), | ||
JsonWebTokenError: require('./lib/JsonWebTokenError'), | ||
NotBeforeError: require('./lib/NotBeforeError'), | ||
TokenExpiredError: require('./lib/TokenExpiredError'), | ||
}; | ||
JWT.sign = require('./sign'); | ||
JWT.verify = function(jwtString, secretOrPublicKey, options, callback) { | ||
if ((typeof options === 'function') && !callback) { | ||
callback = options; | ||
options = {}; | ||
} | ||
if (!options) options = {}; | ||
var done; | ||
if (callback) { | ||
done = function() { | ||
var args = Array.prototype.slice.call(arguments, 0); | ||
return process.nextTick(function() { | ||
callback.apply(null, args); | ||
}); | ||
}; | ||
} else { | ||
done = function(err, data) { | ||
if (err) throw err; | ||
return data; | ||
}; | ||
} | ||
if (!jwtString){ | ||
return done(new JsonWebTokenError('jwt must be provided')); | ||
} | ||
var parts = jwtString.split('.'); | ||
if (parts.length !== 3){ | ||
return done(new JsonWebTokenError('jwt malformed')); | ||
} | ||
var hasSignature = parts[2].trim() !== ''; | ||
if (!hasSignature && secretOrPublicKey){ | ||
return done(new JsonWebTokenError('jwt signature is required')); | ||
} | ||
if (hasSignature && !secretOrPublicKey) { | ||
return done(new JsonWebTokenError('secret or public key must be provided')); | ||
} | ||
if (!hasSignature && !options.algorithms) { | ||
options.algorithms = ['none']; | ||
} | ||
if (!options.algorithms) { | ||
options.algorithms = ~secretOrPublicKey.toString().indexOf('BEGIN CERTIFICATE') || | ||
~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' ]; | ||
} | ||
var decodedToken; | ||
try { | ||
decodedToken = jws.decode(jwtString); | ||
} catch(err) { | ||
return done(new JsonWebTokenError('invalid token')); | ||
} | ||
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, header.alg, secretOrPublicKey); | ||
} catch (e) { | ||
return done(e); | ||
} | ||
if (!valid) | ||
return done(new JsonWebTokenError('invalid signature')); | ||
var payload; | ||
try { | ||
payload = JWT.decode(jwtString); | ||
} catch(err) { | ||
return done(err); | ||
} | ||
if (typeof payload.nbf !== 'undefined' && !options.ignoreNotBefore) { | ||
if (typeof payload.nbf !== 'number') { | ||
return done(new JsonWebTokenError('invalid nbf value')); | ||
} | ||
if (payload.nbf > Math.floor(Date.now() / 1000) + (options.clockTolerance || 0)) { | ||
return done(new NotBeforeError('jwt not active', new Date(payload.nbf * 1000))); | ||
} | ||
} | ||
if (typeof payload.exp !== 'undefined' && !options.ignoreExpiration) { | ||
if (typeof payload.exp !== 'number') { | ||
return done(new JsonWebTokenError('invalid exp value')); | ||
} | ||
if (Math.floor(Date.now() / 1000) >= payload.exp + (options.clockTolerance || 0)) { | ||
return done(new TokenExpiredError('jwt expired', new Date(payload.exp * 1000))); | ||
} | ||
} | ||
if (options.audience) { | ||
var audiences = Array.isArray(options.audience)? options.audience : [options.audience]; | ||
var target = Array.isArray(payload.aud) ? payload.aud : [payload.aud]; | ||
var match = target.some(function(aud) { return audiences.indexOf(aud) != -1; }); | ||
if (!match) | ||
return done(new JsonWebTokenError('jwt audience invalid. expected: ' + audiences.join(' or '))); | ||
} | ||
if (options.issuer) { | ||
var invalid_issuer = | ||
(typeof options.issuer === 'string' && payload.iss !== options.issuer) || | ||
(Array.isArray(options.issuer) && options.issuer.indexOf(payload.iss) === -1); | ||
if (invalid_issuer) { | ||
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 jwtid invalid. expected: ' + options.jwtid)); | ||
} | ||
} | ||
if (options.maxAge) { | ||
var maxAge = ms(options.maxAge); | ||
if (typeof payload.iat !== 'number') { | ||
return done(new JsonWebTokenError('iat required when maxAge is specified')); | ||
} | ||
if (Date.now() - (payload.iat * 1000) > maxAge + (options.clockTolerance || 0) * 1000) { | ||
return done(new TokenExpiredError('maxAge exceeded', new Date(payload.iat * 1000 + maxAge))); | ||
} | ||
} | ||
return done(null, payload); | ||
}; |
{ | ||
"name": "jsonwebtoken", | ||
"version": "7.1.0", | ||
"version": "7.1.1", | ||
"description": "JSON Web Token implementation (symmetric and asymmetric)", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -37,2 +37,2 @@ var jwt = require('../index'); | ||
}); | ||
}); |
@@ -49,2 +49,23 @@ var jwt = require('../index'); | ||
it('should not mutate options', function (done) { | ||
var header = { alg: 'none' }; | ||
var payload = { iat: Math.floor(Date.now() / 1000 ) }; | ||
var options = {typ: 'JWT'}; | ||
var signed = jws.sign({ | ||
header: header, | ||
payload: payload, | ||
secret: priv, | ||
encoding: 'utf8' | ||
}); | ||
jwt.verify(signed, null, options, function(err) { | ||
assert.isNull(err); | ||
assert.deepEqual(Object.keys(options).length, 1); | ||
done(); | ||
}); | ||
}); | ||
describe('expiration', function () { | ||
@@ -51,0 +72,0 @@ // { foo: 'bar', iat: 1437018582, exp: 1437018583 } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
85926
40
1242