diff --git a/src/auth/OAUthWithIDTokenValidation.js b/src/auth/OAUthWithIDTokenValidation.js index b9833f948..9ff263a3b 100644 --- a/src/auth/OAUthWithIDTokenValidation.js +++ b/src/auth/OAUthWithIDTokenValidation.js @@ -4,6 +4,9 @@ var Promise = require('bluebird'); var ArgumentError = require('rest-facade').ArgumentError; +var HS256_IGNORE_VALIDATION_MESSAGE = + 'Validation of `id_token` requires a `clientSecret` when using the HS256 algorithm. To ensure tokens are validated, please switch the signing algorithm to RS256 or provide a `clientSecret` in the constructor.'; + /** * @class * Abstracts the `oauth.create` method with additional id_token validation @@ -58,6 +61,9 @@ OAUthWithIDTokenValidation.prototype.create = function(params, data, cb) { if (r.id_token) { function getKey(header, callback) { if (header.alg === 'HS256') { + if (!_this.clientSecret) { + return callback({ message: HS256_IGNORE_VALIDATION_MESSAGE }); + } return callback(null, Buffer.from(_this.clientSecret, 'base64')); } _this._jwksClient.getSigningKey(header.kid, function(err, key) { @@ -77,11 +83,15 @@ OAUthWithIDTokenValidation.prototype.create = function(params, data, cb) { audience: this.clientId, issuer: 'https://' + this.domain + '/' }, - function(err, payload) { - if (err) { - return rej(err); + function(err) { + if (!err) { + return res(r); + } + if (err.message && err.message.includes(HS256_IGNORE_VALIDATION_MESSAGE)) { + console.warn(HS256_IGNORE_VALIDATION_MESSAGE); + return res(r); } - return res(r); + return rej(err); } ); }); diff --git a/test/auth/oauth-with-idtoken-validation.tests.js b/test/auth/oauth-with-idtoken-validation.tests.js index 8e53a2490..2f8dc4fb4 100644 --- a/test/auth/oauth-with-idtoken-validation.tests.js +++ b/test/auth/oauth-with-idtoken-validation.tests.js @@ -128,7 +128,7 @@ describe('OAUthWithIDTokenValidation', function() { done(); }); }); - it('Calls uses secret as key when header.alg === HS256', function(done) { + it('Uses `clientSecret` as key when header.alg === HS256 and there is a user secret', function(done) { var oauth = { create: function() { return new Promise(res => res({ id_token: 'foobar' })); @@ -145,6 +145,27 @@ describe('OAUthWithIDTokenValidation', function() { }); oauthWithValidation.create(PARAMS, DATA); }); + it('Returns unvalidated response when header.alg === HS256 and there is no user secret', function(done) { + var oauth = { + create: function() { + return new Promise(res => res({ id_token: 'foobar' })); + } + }; + sinon.stub(jwt, 'verify', function(idtoken, getKey, options, callback) { + getKey({ alg: 'HS256' }, function(err, key) { + expect(err.message).to.contain( + 'Validation of `id_token` requires a `clientSecret` when using the HS256 algorithm. To ensure tokens are validated, please switch the signing algorithm to RS256 or provide a `clientSecret` in the constructor.' + ); + callback(err, key); + }); + }); + var oauthWithValidation = new OAUthWithIDTokenValidation(oauth, {}); + oauthWithValidation.create(PARAMS, DATA, function(err, response) { + expect(err).to.be.null; + expect(response).to.be.eql({ id_token: 'foobar' }); + done(); + }); + }); describe('when header.alg !== HS256', function() { it('creates a jwksClient with the correct jwksUri', function(done) { var oauth = {