idtoken-verifier
Advanced tools
Comparing version 1.1.2 to 1.2.0
# Change Log | ||
## [v1.2.0](https://github.com/auth0/idtoken-verifier/tree/v1.2.0) (2018-03-21) | ||
[Full Changelog](https://github.com/auth0/idtoken-verifier/compare/v1.1.2...v1.2.0) | ||
**Added** | ||
- Add option to set the endpoint to fetch the jwks.json file [\#19](https://github.com/auth0/idtoken-verifier/pull/19) ([luisrudge](https://github.com/luisrudge)) | ||
- Adding access_token validation method `validateAccessToken` [\#17](https://github.com/auth0/idtoken-verifier/pull/17) ([luisrudge](https://github.com/luisrudge)) | ||
## [v1.1.2](https://github.com/auth0/idtoken-verifier/tree/v1.1.2) (2018-03-01) | ||
@@ -4,0 +11,0 @@ [Full Changelog](https://github.com/auth0/idtoken-verifier/compare/v1.1.1...v1.1.2) |
{ | ||
"name": "idtoken-verifier", | ||
"version": "1.1.2", | ||
"version": "1.2.0", | ||
"description": "A lightweight library to decode and verify RS JWT meant for the browser.", | ||
@@ -14,3 +14,3 @@ "main": "src/index.js", | ||
"ci:coverage": "codecov", | ||
"lint": "eslint ./src", | ||
"lint": "eslint ./src --fix", | ||
"jsdoc:generate": "jsdoc --configure .jsdoc.json --verbose", | ||
@@ -17,0 +17,0 @@ "release:clean": "node scripts/cleanup.js", |
@@ -17,5 +17,5 @@ # idtoken-verifier | ||
var verifier = new IdTokenVerifier({ | ||
issuer: 'https://my.auth0.com/', | ||
audience: 'gYSNlU4YC4V1YPdqq8zPQcup6rJw1Mbt' | ||
}); | ||
issuer: 'https://my.auth0.com/', | ||
audience: 'gYSNlU4YC4V1YPdqq8zPQcup6rJw1Mbt' | ||
}); | ||
@@ -39,2 +39,3 @@ verifier.verify(id_token, nonce, function(error, payload) { | ||
+ jwksCache: the verifier will try to fetch the JWKS from the `/.well-known/jwks.json` endpoint each time it verifies a token. You can provide a cache to store the keys and avoid repeated requests. For the contract, check [this example](https://github.com/auth0/jwt-js-rsa-verification/blob/master/src/helpers/dummy-cache.js). | ||
+ jwksURI: A valid, direct URI to fetch the JSON Web Key Set (JWKS). Defaults to `${id_token.iss}/.well-known/jwks.json` | ||
- callback | ||
@@ -41,0 +42,0 @@ + error: the validation error if any, null otherwise |
@@ -63,2 +63,14 @@ var base64 = require('base64-js'); | ||
function base64ToBase64Url(base64String) { | ||
var SAFE_URL_ENCODING_MAPPING = { | ||
"+": "-", | ||
"/": "_", | ||
"=": "" | ||
}; | ||
return base64String.replace(/[+/=]/g, function(m) { | ||
return SAFE_URL_ENCODING_MAPPING[m]; | ||
}); | ||
} | ||
module.exports = { | ||
@@ -71,3 +83,4 @@ encodeString: encodeString, | ||
byteArrayToHex: byteArrayToHex, | ||
decodeToHEX: decodeToHEX | ||
decodeToHEX: decodeToHEX, | ||
base64ToBase64Url: base64ToBase64Url | ||
}; |
@@ -16,3 +16,3 @@ var urljoin = require('url-join'); | ||
function getJWKS(options, cb) { | ||
var url = urljoin(options.iss, '.well-known', 'jwks.json'); | ||
var url = options.jwksURI || urljoin(options.iss, '.well-known', 'jwks.json'); | ||
@@ -27,3 +27,3 @@ return request | ||
if (err) { | ||
cb(err); | ||
return cb(err); | ||
} | ||
@@ -39,3 +39,3 @@ | ||
cb(null, process(matchingKey)); | ||
return cb(null, process(matchingKey)); | ||
}); | ||
@@ -42,0 +42,0 @@ } |
@@ -0,1 +1,5 @@ | ||
var sha256 = require('crypto-js/sha256'); | ||
var cryptoBase64 = require('crypto-js/enc-base64'); | ||
var cryptoHex = require('crypto-js/enc-hex'); | ||
var RSAVerifier = require('./helpers/rsa-verifier'); | ||
@@ -17,2 +21,3 @@ var base64 = require('./helpers/base64'); | ||
* @param {Object} [parameters.jwksCache] cache for JSON Web Token Keys. By default it has no cache | ||
* @param {String} [parameters.jwksURI] A valid, direct URI to fetch the JSON Web Key Set (JWKS). | ||
* @param {String} [parameters.expectedAlg='RS256'] algorithm in which the id_token was signed | ||
@@ -32,2 +37,3 @@ * and will be used to validate | ||
this.__disableExpirationCheck = options.__disableExpirationCheck || false; | ||
this.jwksURI = options.jwksURI; | ||
@@ -192,2 +198,3 @@ if (this.leeway < 0 || this.leeway > 60) { | ||
jwks.getJWKS({ | ||
jwksURI: this.jwksURI, | ||
iss: iss, | ||
@@ -251,2 +258,38 @@ kid: kid | ||
/** | ||
* @callback validateAccessTokenCallback | ||
* @param {Error} [err] error returned if the validation cannot be performed | ||
* or the token is invalid. If there is no error, then the access_token is valid. | ||
*/ | ||
/** | ||
* Validates an access_token based on {@link http://openid.net/specs/openid-connect-core-1_0.html#ImplicitTokenValidation}. | ||
* The id_token from where the alg and atHash parameters are taken, | ||
* should be decoded and verified before using thisfunction | ||
* | ||
* @method validateAccessToken | ||
* @param {String} access_token the access_token | ||
* @param {String} alg The algorithm defined in the header of the | ||
* previously verified id_token under the "alg" claim. | ||
* @param {String} atHash The "at_hash" value included in the payload | ||
* of the previously verified id_token. | ||
* @param {validateAccessTokenCallback} cb callback used to notify the results of the validation. | ||
*/ | ||
IdTokenVerifier.prototype.validateAccessToken = function (accessToken, alg, atHash, cb) { | ||
if (this.expectedAlg !== alg) { | ||
return cb(new error.TokenValidationError('Algorithm ' + alg + | ||
' is not supported. (Expected alg: ' + this.expectedAlg + ')')); | ||
} | ||
var sha256AccessToken = sha256(accessToken); | ||
var hashToHex = cryptoHex.stringify(sha256AccessToken); | ||
var hashToHexFirstHalf = hashToHex.substring(0, hashToHex.length / 2); | ||
var hashFirstHalfWordArray = cryptoHex.parse(hashToHexFirstHalf); | ||
var hashFirstHalfBase64 = cryptoBase64.stringify(hashFirstHalfWordArray); | ||
var hashFirstHalfBase64SafeUrl = base64.base64ToBase64Url(hashFirstHalfBase64); | ||
if (hashFirstHalfBase64SafeUrl !== atHash) { | ||
return cb(new error.TokenValidationError('Invalid access_token')); | ||
} | ||
return cb(null); | ||
}; | ||
module.exports = IdTokenVerifier; |
@@ -1,5 +0,5 @@ | ||
// Generated file by luis on Thu Mar 01 2018 16:29:27 GMT-0300 (-03); | ||
// Generated file by luis on Wed Mar 21 2018 14:58:11 GMT-0300 (-03); | ||
module.exports = { | ||
"version": "1.1.2", | ||
"version": "1.2.0", | ||
"name": "idtoken-verifier" | ||
}; |
@@ -57,2 +57,6 @@ var expect = require('expect.js'); | ||
it('base64ToBase64Url', function() { | ||
expect(base64.base64ToBase64Url('aa/bb+cc=')).to.eql('aa_bb-cc'); | ||
}); | ||
}); |
@@ -252,2 +252,15 @@ var expect = require('expect.js'); | ||
describe('getRsaVerifier', function () { | ||
it('should pass options.jwksURI through ', function(done){ | ||
var mockJwks = { | ||
getJWKS: function(options){ | ||
expect(options.jwksURI).to.be('https://example.com/'); | ||
done(); | ||
} | ||
}; | ||
var revert = IdTokenVerifier.__set__({jwks: mockJwks}); | ||
var verifier = new IdTokenVerifier({jwksURI: 'https://example.com/'}); | ||
verifier.getRsaVerifier('iss', 'kid'); | ||
revert(); | ||
}); | ||
it('should call callback once with error when an error is returned from jwks.getJWKS', function(){ | ||
@@ -279,1 +292,54 @@ var mockJwks = { | ||
}); | ||
describe('access_token validation', function() { | ||
describe('With empty access_tokens', function() { | ||
[null, undefined, ''].forEach(function(at) { | ||
it('should throw when access_token is `' + at + '`', function(done) { | ||
var access_token = at; | ||
var alg = 'RS256'; | ||
var at_hash = 'at_hash'; | ||
var itv = new IdTokenVerifier(); | ||
itv.validateAccessToken(access_token, alg, at_hash, function(err) { | ||
expect(err.name).to.be('TokenValidationError'); | ||
expect(err.message).to.be('Invalid access_token'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should throw an error with HS256 id_token', function(done) { | ||
var access_token = "YTvJYcYrrZYHUXLZK5leLnfmD5ZIA_EA"; | ||
var alg = 'HS256'; | ||
var at_hash = 'at_hash'; | ||
var itv = new IdTokenVerifier(); | ||
itv.validateAccessToken(access_token, alg, at_hash, function(err) { | ||
expect(err.name).to.be('TokenValidationError'); | ||
expect(err.message).to.be('Algorithm HS256 is not supported. (Expected alg: RS256)'); | ||
done(); | ||
}); | ||
}); | ||
it('should throw an error when access_token is invalid', function(done) { | ||
var access_token = "not an access token"; | ||
var alg = 'RS256'; | ||
var at_hash = 'cdukoaUswM9bo_yzrgVcrw'; | ||
var itv = new IdTokenVerifier(); | ||
itv.validateAccessToken(access_token, alg, at_hash, function(err) { | ||
expect(err.name).to.be('TokenValidationError'); | ||
expect(err.message).to.be('Invalid access_token'); | ||
done(); | ||
}); | ||
}); | ||
it('should validate access_token with RS256 id_token', function(done) { | ||
var access_token = "YTvJYcYrrZYHUXLZK5leLnfmD5ZIA_EA"; | ||
var alg = 'RS256'; | ||
var at_hash = 'cdukoaUswM9bo_yzrgVcrw'; | ||
var itv = new IdTokenVerifier(); | ||
itv.validateAccessToken(access_token, alg, at_hash, function(err) { | ||
expect(err).to.be(null); | ||
done(); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
1688448
68
2099
94