Comparing version 1.0.1 to 1.0.3
@@ -269,2 +269,26 @@ [ | ||
{ | ||
"type": "MISSING_IAT", | ||
"fields": [ | ||
{ | ||
"key": "message", | ||
"value": "iat field is missing in the JWT payload.", | ||
"doc": null | ||
}, | ||
{ | ||
"key": "level", | ||
"value": "info", | ||
"doc": null | ||
}, | ||
{ | ||
"key": "namespace", | ||
"value": "JWTPAYLOAD", | ||
"doc": null | ||
} | ||
], | ||
"doc": { | ||
"description": "Iat is required.", | ||
"tags": [] | ||
} | ||
}, | ||
{ | ||
"type": "INVALID_EXP", | ||
@@ -342,2 +366,26 @@ "fields": [ | ||
{ | ||
"type": "NO_FRESH_JWT", | ||
"fields": [ | ||
{ | ||
"key": "message", | ||
"value": "JWT has discarded by client. No fresh JWT.", | ||
"doc": null | ||
}, | ||
{ | ||
"key": "level", | ||
"value": "info", | ||
"doc": null | ||
}, | ||
{ | ||
"key": "namespace", | ||
"value": "JWTPAYLOAD", | ||
"doc": null | ||
} | ||
], | ||
"doc": { | ||
"description": "The jwt has discarded by client. Current time is greater than client expiration.", | ||
"tags": [] | ||
} | ||
}, | ||
{ | ||
"type": "FUTURE_JWT", | ||
@@ -344,0 +392,0 @@ "fields": [ |
@@ -127,2 +127,11 @@ /** | ||
/** | ||
* Iat is required. | ||
*/ | ||
MISSING_IAT: { | ||
message: 'iat field is missing in the JWT payload.', | ||
level: 'info', | ||
namespace: 'JWTPAYLOAD' | ||
}, | ||
/** | ||
* Invalid exp value. | ||
@@ -155,2 +164,11 @@ */ | ||
/** | ||
* The jwt has discarded by client. Current time is greater than client expiration. | ||
*/ | ||
NO_FRESH_JWT: { | ||
message: 'JWT has discarded by client. No fresh JWT.', | ||
level: 'info', | ||
namespace: 'JWTPAYLOAD' | ||
}, | ||
/** | ||
* The jwt has an invalid date. Perhaps the machine clocks has some differences or you may suffering an attack. | ||
@@ -157,0 +175,0 @@ */ |
@@ -54,329 +54,330 @@ /** | ||
var config = {}; | ||
/** | ||
* The exported API | ||
* @type {*} | ||
* @return {Object} | ||
*/ | ||
module.exports = function(configuration) { | ||
function base64urlEscape(str) { | ||
return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); | ||
} | ||
var config = {}; | ||
function base64urlUnescape(str) { | ||
str += new Array(5 - str.length % 4).join('='); | ||
return str.replace(/\-/g, '+').replace(/_/g, '/'); | ||
} | ||
function base64urlEscape(str) { | ||
return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); | ||
} | ||
function base64urlEncode(str) { | ||
return base64urlEscape(new Buffer(str).toString('base64')); | ||
} | ||
function base64urlDecode(str) { | ||
return new Buffer(base64urlUnescape(str), 'base64'); | ||
} | ||
function encodeBase64url(base64) { | ||
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, ''); | ||
} | ||
function convertSlowBufToBuf(slowBuffer) { | ||
var buffer = new Buffer(slowBuffer.length); | ||
slowBuffer.copy(buffer); | ||
return buffer; | ||
} | ||
function readJWTHeader(base64header) { | ||
var headerStr = base64urlDecode(base64header); | ||
var header = JSON.parse(headerStr); | ||
return header; | ||
} | ||
function getEncryptionAndHashAlgoritms(encHeaderValue) { | ||
var algs = encHeaderValue.split('-'); | ||
var cipherAlgorithm = cipherMap[algs[0]]; | ||
var hashAlgorithm = hashAlgorithms[algs[1]]; | ||
if (!cipherAlgorithm) { | ||
throw errors.ALGORITHM_NOT_SUPPORTED('Invalid encryption algorithm: ' + algs[0]); | ||
function base64urlUnescape(str) { | ||
str += new Array(5 - str.length % 4).join('='); | ||
return str.replace(/\-/g, '+').replace(/_/g, '/'); | ||
} | ||
if (!hashAlgorithm) { | ||
throw errors.ALGORITHM_NOT_SUPPORTED('Invalid hash algorithm: ' + algs[1]); | ||
function base64urlEncode(str) { | ||
return base64urlEscape(new Buffer(str).toString('base64')); | ||
} | ||
return { | ||
cipherAlgorithm: cipherAlgorithm, | ||
hashAlgorithm: hashAlgorithm | ||
}; | ||
} | ||
function encodeJWT(payload, header, key) { | ||
if (!key) { | ||
throw errors.MISSING_REQUIRED_KEY(); | ||
function base64urlDecode(str) { | ||
return new Buffer(base64urlUnescape(str), 'base64'); | ||
} | ||
if (!hashAlgorithms[header.alg]) { | ||
throw errors.ALGORITHM_NOT_SUPPORTED(); | ||
function encodeBase64url(base64) { | ||
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, ''); | ||
} | ||
// header, typ is fixed value. | ||
if (!header.kid) { | ||
throw errors.MISSING_REQUIRED_KID(); | ||
function convertSlowBufToBuf(slowBuffer) { | ||
var buffer = new Buffer(slowBuffer.length); | ||
slowBuffer.copy(buffer); | ||
return buffer; | ||
} | ||
// create segments, all segment should be base64 string | ||
var segments = []; | ||
segments.push(base64urlEncode(JSON.stringify(header))); | ||
segments.push(base64urlEncode(JSON.stringify(payload))); | ||
var signer = jwa(header.alg); | ||
//If we use RS256, the key is the private Key | ||
if (header.alg.indexOf('HS') === 0) { | ||
key = new Buffer(key, 'hex'); | ||
function readJWTHeader(base64header) { | ||
var headerStr = base64urlDecode(base64header); | ||
var header = JSON.parse(headerStr); | ||
return header; | ||
} | ||
segments.push(signer.sign(segments.join('.'), key)); | ||
return segments.join('.'); | ||
} | ||
function getEncryptionAndHashAlgoritms(encHeaderValue) { | ||
var algs = encHeaderValue.split('-'); | ||
var cipherAlgorithm = cipherMap[algs[0]]; | ||
var hashAlgorithm = hashAlgorithms[algs[1]]; | ||
function decodeJWT(token, key) { | ||
var segments = token.split('.'); | ||
if (segments.length !== 3) { | ||
throw errors.SEGMENTS_NUMBER_ERROR(segments.length); | ||
if (!cipherAlgorithm) { | ||
throw errors.ALGORITHM_NOT_SUPPORTED('Invalid encryption algorithm: ' + algs[0]); | ||
} | ||
if (!hashAlgorithm) { | ||
throw errors.ALGORITHM_NOT_SUPPORTED('Invalid hash algorithm: ' + algs[1]); | ||
} | ||
return { | ||
cipherAlgorithm: cipherAlgorithm, | ||
hashAlgorithm: hashAlgorithm | ||
}; | ||
} | ||
var header = readJWTHeader(segments[0]); | ||
function encodeJWT(payload, header, key) { | ||
if (!key) { | ||
throw errors.MISSING_REQUIRED_KEY(); | ||
} | ||
if (!header.kid) { | ||
throw errors.MISSING_REQUIRED_KID(); | ||
} | ||
if (!hashAlgorithms[header.alg]) { | ||
throw errors.ALGORITHM_NOT_SUPPORTED(); | ||
} | ||
var algorithm = header.alg || 'HS256'; | ||
// header, typ is fixed value. | ||
if (!header.kid) { | ||
throw errors.MISSING_REQUIRED_KID(); | ||
} | ||
if (!hashAlgorithms[header.alg]) { | ||
throw errors.ALGORITHM_NOT_SUPPORTED(); | ||
} | ||
// create segments, all segment should be base64 string | ||
var segments = []; | ||
segments.push(base64urlEncode(JSON.stringify(header))); | ||
segments.push(base64urlEncode(JSON.stringify(payload))); | ||
var signer = jwa(header.alg); | ||
//If we use RS256, the key is the private Key | ||
if (header.alg.indexOf('HS') === 0) { | ||
key = new Buffer(key, 'hex'); | ||
} | ||
segments.push(signer.sign(segments.join('.'), key)); | ||
var signer = jwa(algorithm); | ||
if (algorithm.indexOf('HS') === 0) { | ||
key = new Buffer(key, 'hex'); | ||
return segments.join('.'); | ||
} | ||
if (!signer.verify(segments[0] + '.' + segments[1], segments[2], key)) { | ||
throw errors.WRONG_TOKEN_SIGNATURE(); | ||
} | ||
var payloadStr = base64urlDecode(segments[1]); | ||
function decodeJWT(token, key) { | ||
var segments = token.split('.'); | ||
if (segments.length !== 3) { | ||
throw errors.SEGMENTS_NUMBER_ERROR(segments.length); | ||
} | ||
return { | ||
header: header, | ||
payload: JSON.parse(payloadStr) | ||
}; | ||
} | ||
var header = readJWTHeader(segments[0]); | ||
function decryptJWT(token, encKey, hashKey) { | ||
var segments = token.split('.'); | ||
if (segments.length !== 5) { | ||
throw errors.SEGMENTS_NUMBER_ERROR(segments.length); | ||
} | ||
if (!header.kid) { | ||
throw errors.MISSING_REQUIRED_KID(); | ||
} | ||
var header = readJWTHeader(segments[0]); | ||
var algorithm = header.alg || 'HS256'; | ||
if (!header.kid) { | ||
throw errors.MISSING_REQUIRED_KID(); | ||
} | ||
if (!hashAlgorithms[header.alg]) { | ||
throw errors.ALGORITHM_NOT_SUPPORTED(); | ||
} | ||
var algorithms = getEncryptionAndHashAlgoritms(header.enc); | ||
var signer = jwa(algorithm); | ||
if (algorithm.indexOf('HS') === 0) { | ||
key = new Buffer(key, 'hex'); | ||
} | ||
if (!signer.verify(segments[0] + '.' + segments[1], segments[2], key)) { | ||
throw errors.WRONG_TOKEN_SIGNATURE(); | ||
} | ||
var initializationVector = null; | ||
if (segments[2]) { | ||
initializationVector = base64urlDecode(segments[2]); | ||
} | ||
var payloadStr = base64urlDecode(segments[1]); | ||
var cypherText = null; | ||
if (segments[3] === null || segments[3] === '') { | ||
throw errors.INVALID_FOURTH_SEGMENT(); | ||
} else { | ||
cypherText = base64urlDecode(segments[3]); | ||
return { | ||
header: header, | ||
payload: JSON.parse(payloadStr) | ||
}; | ||
} | ||
var origAuthenticationTag = null; | ||
if (segments[4]) { | ||
origAuthenticationTag = segments[4]; | ||
} | ||
function decryptJWT(token, encKey, hashKey) { | ||
var segments = token.split('.'); | ||
if (segments.length !== 5) { | ||
throw errors.SEGMENTS_NUMBER_ERROR(segments.length); | ||
} | ||
var encKeyBuffer = new Buffer(encKey, 'hex'); | ||
var result, hashBuf; | ||
try { | ||
var decipher = crypto.createDecipheriv(algorithms.cipherAlgorithm, encKeyBuffer, initializationVector); | ||
var header = readJWTHeader(segments[0]); | ||
decipher.setAutoPadding(true); | ||
if (!header.kid) { | ||
throw errors.MISSING_REQUIRED_KID(); | ||
} | ||
var mainBody = decipher.update(cypherText); | ||
var endBody = decipher.final(); | ||
result = Buffer.concat([convertSlowBufToBuf(mainBody), convertSlowBufToBuf(endBody)]).toString(); | ||
var algorithms = getEncryptionAndHashAlgoritms(header.enc); | ||
var b64Header = new Buffer(segments[0]); | ||
var iv = new Buffer(initializationVector); | ||
var encryptedBody = new Buffer(cypherText); | ||
var initializationVector = null; | ||
if (segments[2]) { | ||
initializationVector = base64urlDecode(segments[2]); | ||
} | ||
// create al vector | ||
var al = new Buffer(4); | ||
al.writeInt32BE(b64Header.length * 8, 0); | ||
var cypherText = null; | ||
if (segments[3] === null || segments[3] === '') { | ||
throw errors.INVALID_FOURTH_SEGMENT(); | ||
} else { | ||
cypherText = base64urlDecode(segments[3]); | ||
} | ||
var buf4Clear = new Buffer(4); | ||
buf4Clear.fill(0); | ||
var alResult = Buffer.concat([buf4Clear, al]); | ||
var origAuthenticationTag = null; | ||
if (segments[4]) { | ||
origAuthenticationTag = segments[4]; | ||
} | ||
var authTag = new Buffer(Buffer.concat([b64Header, iv, encryptedBody, alResult])); | ||
var encKeyBuffer = new Buffer(encKey, 'hex'); | ||
var result, hashBuf; | ||
try { | ||
var decipher = crypto.createDecipheriv(algorithms.cipherAlgorithm, encKeyBuffer, initializationVector); | ||
var hashKeyBuffer = new Buffer(hashKey, 'hex'); | ||
var authTagHash = crypto.createHmac(algorithms.hashAlgorithm, hashKeyBuffer).update(authTag).digest(); | ||
decipher.setAutoPadding(true); | ||
var authTagHashBuf = convertSlowBufToBuf(authTagHash); | ||
hashBuf = authTagHashBuf.slice(0, authenticationTagBits[algorithms.hashAlgorithm]); | ||
} catch (err) { | ||
debug('Error Decrypt: ', err.message); | ||
throw errors.DECRYPTION_ERROR(': ' + err.message); | ||
} | ||
var mainBody = decipher.update(cypherText); | ||
var endBody = decipher.final(); | ||
result = Buffer.concat([convertSlowBufToBuf(mainBody), convertSlowBufToBuf(endBody)]).toString(); | ||
if (base64urlEscape(hashBuf.toString('base64')) !== origAuthenticationTag) { | ||
throw errors.DECRYPTION_ERROR(''); | ||
} else { | ||
return { | ||
header: header, | ||
payload: JSON.parse(result) | ||
}; | ||
} | ||
} | ||
var b64Header = new Buffer(segments[0]); | ||
var iv = new Buffer(initializationVector); | ||
var encryptedBody = new Buffer(cypherText); | ||
function generateRandomInitializationVector() { | ||
var iv = []; | ||
for (var i = 0; i < 16; i++) { | ||
iv.push(Math.round(Math.random() * 255)); | ||
} | ||
// create al vector | ||
var al = new Buffer(4); | ||
al.writeInt32BE(b64Header.length * 8, 0); | ||
return new Buffer(iv); | ||
} | ||
var buf4Clear = new Buffer(4); | ||
buf4Clear.fill(0); | ||
var alResult = Buffer.concat([buf4Clear, al]); | ||
function encryptJWT(payload, header, encKey, hashKey) { | ||
var authTag = new Buffer(Buffer.concat([b64Header, iv, encryptedBody, alResult])); | ||
header = _.defaults(header, { | ||
alg: 'dir', | ||
enc: 'A256CBC-HS512' | ||
}); | ||
var hashKeyBuffer = new Buffer(hashKey, 'hex'); | ||
var authTagHash = crypto.createHmac(algorithms.hashAlgorithm, hashKeyBuffer).update(authTag).digest(); | ||
if (!header.kid) { | ||
throw errors.MISSING_REQUIRED_KID(); | ||
var authTagHashBuf = convertSlowBufToBuf(authTagHash); | ||
hashBuf = authTagHashBuf.slice(0, authenticationTagBits[algorithms.hashAlgorithm]); | ||
} catch (err) { | ||
debug('Error Decrypt: ', err.message); | ||
throw errors.DECRYPTION_ERROR(': ' + err.message); | ||
} | ||
if (base64urlEscape(hashBuf.toString('base64')) !== origAuthenticationTag) { | ||
throw errors.DECRYPTION_ERROR(''); | ||
} else { | ||
return { | ||
header: header, | ||
payload: JSON.parse(result) | ||
}; | ||
} | ||
} | ||
var algorithms = getEncryptionAndHashAlgoritms(header.enc); | ||
function generateRandomInitializationVector() { | ||
var iv = []; | ||
for (var i = 0; i < 16; i++) { | ||
iv.push(Math.round(Math.random() * 255)); | ||
} | ||
var iv = generateRandomInitializationVector(); | ||
return new Buffer(iv); | ||
} | ||
var segments = []; | ||
function encryptJWT(payload, header, encKey, hashKey) { | ||
var b64Header = encodeBase64url(new Buffer(JSON.stringify(header)).toString('base64')); | ||
segments.push(b64Header); | ||
header = _.defaults(header, { | ||
alg: 'dir', | ||
enc: 'A256CBC-HS512' | ||
}); | ||
var b64Jek = ''; | ||
segments.push(b64Jek); | ||
if (!header.kid) { | ||
throw errors.MISSING_REQUIRED_KID(); | ||
} | ||
var b64IV = encodeBase64url(iv.toString('base64')); | ||
segments.push(b64IV); | ||
var algorithms = getEncryptionAndHashAlgoritms(header.enc); | ||
var encKeyBuffer = new Buffer(encKey, 'hex'); | ||
var cipher = crypto.createCipheriv(algorithms.cipherAlgorithm, encKeyBuffer, iv); | ||
var iv = generateRandomInitializationVector(); | ||
var cipherTextBegin = cipher.update(new Buffer(JSON.stringify(payload), 'utf8')); | ||
var segments = []; | ||
var cipherTextEnd = cipher.final(); | ||
var b64Header = encodeBase64url(new Buffer(JSON.stringify(header)).toString('base64')); | ||
segments.push(b64Header); | ||
var cipherTextBuf = Buffer.concat([convertSlowBufToBuf(cipherTextBegin), convertSlowBufToBuf(cipherTextEnd)]); | ||
var b64Jek = ''; | ||
segments.push(b64Jek); | ||
var b64CipherText = encodeBase64url(cipherTextBuf.toString('base64')); | ||
segments.push(b64CipherText); | ||
var b64IV = encodeBase64url(iv.toString('base64')); | ||
segments.push(b64IV); | ||
// Calculate AuthTag | ||
var encKeyBuffer = new Buffer(encKey, 'hex'); | ||
var cipher = crypto.createCipheriv(algorithms.cipherAlgorithm, encKeyBuffer, iv); | ||
var b64HeaderBuf = new Buffer(b64Header); | ||
var cipherTextBegin = cipher.update(new Buffer(JSON.stringify(payload), 'utf8')); | ||
// We have iv Buffer and cipherTextBuf Buffer calculated. | ||
var cipherTextEnd = cipher.final(); | ||
var al = new Buffer(4); | ||
al.writeInt32BE(b64HeaderBuf.length * 8, 0); | ||
var cipherTextBuf = Buffer.concat([convertSlowBufToBuf(cipherTextBegin), convertSlowBufToBuf(cipherTextEnd)]); | ||
var buf4Clear = new Buffer(4); | ||
buf4Clear.fill(0); | ||
var b64CipherText = encodeBase64url(cipherTextBuf.toString('base64')); | ||
segments.push(b64CipherText); | ||
var alResult = Buffer.concat([buf4Clear, al]); | ||
// Calculate AuthTag | ||
var authTag = new Buffer(Buffer.concat([b64HeaderBuf, iv, cipherTextBuf, alResult])); | ||
var b64HeaderBuf = new Buffer(b64Header); | ||
var hashKeyBuffer = new Buffer(hashKey, 'hex'); | ||
var base64str = crypto.createHmac(algorithms.hashAlgorithm, hashKeyBuffer).update(authTag).digest(); | ||
// We have iv Buffer and cipherTextBuf Buffer calculated. | ||
var buf = convertSlowBufToBuf(base64str); | ||
var al = new Buffer(4); | ||
al.writeInt32BE(b64HeaderBuf.length * 8, 0); | ||
var result = buf.slice(0, authenticationTagBits[algorithms.hashAlgorithm]); | ||
var buf4Clear = new Buffer(4); | ||
buf4Clear.fill(0); | ||
var b64AuthTag = encodeBase64url(result.toString('base64')); | ||
segments.push(b64AuthTag); | ||
var alResult = Buffer.concat([buf4Clear, al]); | ||
return segments.join('.'); | ||
} | ||
var authTag = new Buffer(Buffer.concat([b64HeaderBuf, iv, cipherTextBuf, alResult])); | ||
function makePayload(payload) { | ||
payload.iat = payload.iat || parseInt(new Date().getTime() / 1000, 10); | ||
payload.exp = payload.exp || payload.iat + config.expiration; | ||
return payload; | ||
} | ||
var hashKeyBuffer = new Buffer(hashKey, 'hex'); | ||
var base64str = crypto.createHmac(algorithms.hashAlgorithm, hashKeyBuffer).update(authTag).digest(); | ||
function checkPayload(token, cb) { | ||
var payload = token.payload; | ||
if (!payload) { | ||
return cb(errors.EMPTY_PAYLOAD()); | ||
var buf = convertSlowBufToBuf(base64str); | ||
var result = buf.slice(0, authenticationTagBits[algorithms.hashAlgorithm]); | ||
var b64AuthTag = encodeBase64url(result.toString('base64')); | ||
segments.push(b64AuthTag); | ||
return segments.join('.'); | ||
} | ||
var currentDate = parseInt(Date.now() / 1000, 10); | ||
if (payload.iat) { | ||
var iatParsed = parseInt(payload.iat, 10); | ||
if (isNaN(iatParsed) || payload.iat !== iatParsed) { | ||
return cb(errors.INVALID_IAT()); | ||
} | ||
function makePayload(payload) { | ||
payload.iat = payload.iat || parseInt(new Date().getTime() / 1000, 10); | ||
payload.exp = payload.exp || payload.iat + config.expiration; | ||
return payload; | ||
} | ||
if (payload.iat > currentDate + config.futureTolerance) { | ||
return cb(errors.FUTURE_JWT()); | ||
function checkPayload(token, cb) { | ||
var payload = token.payload; | ||
if (!payload) { | ||
return cb(errors.EMPTY_PAYLOAD()); | ||
} | ||
if (!payload.exp) { | ||
if (!payload.hasOwnProperty('exp')) { | ||
var expired = iatParsed + config.expiration; | ||
var currentDate = parseInt(Date.now() / 1000, 10); | ||
if (expired <= currentDate) { | ||
return cb(errors.EXPIRED_JWT(), token); | ||
} | ||
if (payload.iat) { | ||
var iatParsed = parseInt(payload.iat, 10); | ||
if (isNaN(iatParsed) || payload.iat !== iatParsed) { | ||
return cb(errors.INVALID_IAT()); | ||
} | ||
if (payload.iat > currentDate + config.futureTolerance) { | ||
return cb(errors.FUTURE_JWT()); | ||
} | ||
} else { | ||
if (payload.hasOwnProperty('iat')) { | ||
return cb(errors.INVALID_IAT()); | ||
} else { | ||
return cb(errors.INVALID_EXP()); | ||
return cb(errors.MISSING_IAT(), token); | ||
} | ||
} | ||
} else { | ||
if (payload.hasOwnProperty('iat')) { | ||
return cb(errors.INVALID_IAT()); | ||
var expLimit = iatParsed + config.expiration; | ||
if (expLimit <= currentDate) { | ||
return cb(errors.NO_FRESH_JWT(), token); | ||
} | ||
} | ||
if (payload.exp) { | ||
var expParsed = parseInt(payload.exp, 10); | ||
if (isNaN(expParsed) || payload.exp !== expParsed) { | ||
return cb(errors.INVALID_EXP()); | ||
if (payload.exp) { | ||
var expParsed = parseInt(payload.exp, 10); | ||
if (isNaN(expParsed) || payload.exp !== expParsed) { | ||
return cb(errors.INVALID_EXP()); | ||
} | ||
if (payload.exp <= currentDate) { | ||
return cb(errors.EXPIRED_JWT(), token); | ||
} | ||
} else { | ||
if (payload.hasOwnProperty('exp')) { | ||
return cb(errors.INVALID_EXP()); | ||
} | ||
} | ||
if (payload.exp <= currentDate) { | ||
return cb(errors.EXPIRED_JWT(), token); | ||
} | ||
return cb(null, token); | ||
} | ||
return cb(null, token); | ||
} | ||
/** | ||
* The exported API | ||
* @type {*} | ||
* @return {Object} | ||
*/ | ||
module.exports = function(configuration) { | ||
if (configuration) { | ||
@@ -383,0 +384,0 @@ config.expiration = configuration.expiration || DEFAULT_CONFIG.expiration; |
{ | ||
"name": "jwt-utils", | ||
"description": "JSON Web Tokens (JWT) utils", | ||
"version": "1.0.1", | ||
"version": "1.0.3", | ||
"license": "Apache-2.0", | ||
@@ -6,0 +6,0 @@ "author": { |
@@ -421,3 +421,3 @@ 'use strict'; | ||
var expiration = 10; | ||
jwtUtils = jwt({expiration: expiration}); | ||
var jwtUtilsMod = jwt({expiration: expiration}); | ||
@@ -431,3 +431,3 @@ var payload = { | ||
jwtUtils.buildJWTEncrypted(payload, {kid: kid}, key, hashKey, function(err, jwt) { | ||
jwtUtilsMod.buildJWTEncrypted(payload, {kid: kid}, key, hashKey, function(err, jwt) { | ||
expect(err).to.not.exist; | ||
@@ -437,4 +437,5 @@ var clock = sinon.useFakeTimers(new Date().getTime()); | ||
jwtUtils.readJWTEncrypted(jwt, key, hashKey, function(err, token) { | ||
expect(err).to.exist; | ||
expect(err).to.be.apiError(errors.EXPIRED_JWT()); | ||
clock.restore(); | ||
expect(err).to.be.apiError(errors.EXPIRED_JWT()); | ||
done(); | ||
@@ -828,2 +829,24 @@ }); | ||
it('should fail when client expired the jwt without taking into account the exp field', function() { | ||
var jwtToken = 'eyJraWQiOiJraWQiLCJhbGciOiJkaXIiLCJlbmMiOiJBMjU' + | ||
'2Q0JDLUhTNTEyIiwiY29yciI6ImNvcnIifQ..Xuaus8N7yqmojQFFFNgxL' + | ||
'g.UCM5odV53W9NEaVvee7fCKb31B1C7wedJn02vapNOf2v3-dmKDaZxt2G' + | ||
'nIDYK-TQ-XkiziRkRtZkjABFRNHPYw.FFduxvzrjIhWu8dQ3MMOVH11-tE' + | ||
'BgE6955c4M9EO3fk'; | ||
var hashKey = '796f75722d7365637265742d6b657923796f75722d7365637265742d6b657923'; | ||
var encKey = '796f75722d7365637265742d6b657923796f75722d7365637265742d6b657923'; | ||
var clock = sinon.useFakeTimers(0, 'Date'); | ||
clock.tick((1443688542000 + 1) * 1000); | ||
var jwtUtilsMod = jwt({expiration: 1}); | ||
jwtUtilsMod.readJWTEncrypted(jwtToken, encKey, hashKey, function(err, token) { | ||
expect(err).to.exist; | ||
expect(err.name).to.be.equal('NO_FRESH_JWT'); | ||
clock.restore(); | ||
}); | ||
}); | ||
}); |
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
79334
1766
0