Skip to content

Commit

Permalink
Merge branch 'master' into feature-doc-search_engine
Browse files Browse the repository at this point in the history
  • Loading branch information
luisrudge authored Sep 28, 2018
2 parents 9a134aa + 58d45f2 commit 07ea7ae
Show file tree
Hide file tree
Showing 7 changed files with 929 additions and 15 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
"homepage": "https://github.com/auth0/node-auth0",
"dependencies": {
"bluebird": "^2.10.2",
"jsonwebtoken": "^8.3.0",
"jwks-rsa": "^1.3.0",
"lru-memoizer": "^1.11.1",
"object.assign": "^4.0.4",
"request": "^2.83.0",
Expand All @@ -49,8 +51,10 @@
"mocha-multi": "^0.11.0",
"moment": "^2.18.1",
"nock": "^3.1.1",
"pem": "^1.13.1",
"prettier": "^1.12.0",
"pretty-quick": "^1.4.1",
"proxyquire": "^2.1.0",
"sinon": "^1.17.1",
"string-replace-webpack-plugin": "0.0.3",
"webpack": "^1.12.14"
Expand Down
97 changes: 97 additions & 0 deletions src/auth/OAUthWithIDTokenValidation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
var jwt = require('jsonwebtoken');
var jwksClient = require('jwks-rsa');
var Promise = require('bluebird');

var ArgumentError = require('rest-facade').ArgumentError;

/**
* @class
* Abstracts the `oauth.create` method with additional id_token validation
* @constructor
* @memberOf module:auth
*
* @param {Object} oauth An instance of @type {OAuthAuthenticator}
* @param {Object} options Authenticator options.
* @param {String} options.domain AuthenticationClient server domain
* @param {String} [options.clientId] Default client ID.
* @param {String} [options.clientSecret] Default client Secret.
* @param {String} [options.supportedAlgorithms] Algorithms that your application expects to receive
*/
var OAUthWithIDTokenValidation = function(oauth, options) {
if (!oauth) {
throw new ArgumentError('Missing OAuthAuthenticator param');
}

if (!options) {
throw new ArgumentError('Missing authenticator options');
}

if (typeof options !== 'object') {
throw new ArgumentError('The authenticator options must be an object');
}

this.oauth = oauth;
this.clientId = options.clientId;
this.clientSecret = options.clientSecret;
this.domain = options.domain;
this.supportedAlgorithms = options.supportedAlgorithms || ['HS256', 'RS256'];
this._jwksClient = jwksClient({
jwksUri: 'https://' + options.domain + '/.well-known/jwks.json'
});
};

/**
* Creates an oauth request and validates the id_token (if any)
*
* @method create
* @memberOf module:auth.OAuthWithIDTokenValidation.prototype
*
* @param {Object} params OAuth parameters that are passed through
* @param {Object} data Custom parameters sent to the OAuth endpoint
* @param {Function} [callback] Callback function
*
* @return {Promise|undefined}
*/
OAUthWithIDTokenValidation.prototype.create = function(params, data, cb) {
const createAndValidate = this.oauth.create(params, data).then(r => {
var _this = this;
if (r.id_token) {
function getKey(header, callback) {
if (header.alg === 'HS256') {
return callback(null, Buffer.from(_this.clientSecret, 'base64'));
}
_this._jwksClient.getSigningKey(header.kid, function(err, key) {
if (err) {
return callback(err);
}
var signingKey = key.publicKey || key.rsaPublicKey;
return callback(null, signingKey);
});
}
return new Promise((res, rej) => {
jwt.verify(
r.id_token,
getKey,
{
algorithms: this.supportedAlgorithms,
audience: this.clientId,
issuer: 'https://' + this.domain + '/'
},
function(err, payload) {
if (err) {
return rej(err);
}
return res(r);
}
);
});
}
return r;
});
if (!cb) {
return createAndValidate;
}
createAndValidate.then(r => cb(null, r)).catch(e => cb(e));
};

module.exports = OAUthWithIDTokenValidation;
18 changes: 11 additions & 7 deletions src/auth/OAuthAuthenticator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ var extend = require('util')._extend;
var ArgumentError = require('rest-facade').ArgumentError;
var RestClient = require('rest-facade').Client;

var OAUthWithIDTokenValidation = require('./OAUthWithIDTokenValidation');

/**
* @class
* Abstracts the sign-in, sign-up and change-password processes for Database &
Expand All @@ -11,7 +13,8 @@ var RestClient = require('rest-facade').Client;
* @memberOf module:auth
*
* @param {Object} options Authenticator options.
* @param {String} options.baseUrl The auth0 account URL.
* @param {String} options.baseUrl The Auth0 account URL.
* @param {String} options.domain AuthenticationClient server domain
* @param {String} [options.clientId] Default client ID.
* @param {String} [options.clientSecret] Default client Secret.
*/
Expand All @@ -34,6 +37,7 @@ var OAuthAuthenticator = function(options) {
};

this.oauth = new RestClient(options.baseUrl + '/oauth/:type', clientOptions);
this.oauthWithIDTokenValidation = new OAUthWithIDTokenValidation(this.oauth, options);
this.clientId = options.clientId;
this.clientSecret = options.clientSecret;
};
Expand Down Expand Up @@ -96,10 +100,10 @@ OAuthAuthenticator.prototype.signIn = function(userData, cb) {
}

if (cb && cb instanceof Function) {
return this.oauth.create(params, data, cb);
return this.oauthWithIDTokenValidation.create(params, data, cb);
}

return this.oauth.create(params, data);
return this.oauthWithIDTokenValidation.create(params, data);
};

/**
Expand Down Expand Up @@ -169,10 +173,10 @@ OAuthAuthenticator.prototype.passwordGrant = function(userData, cb) {
}

if (cb && cb instanceof Function) {
return this.oauth.create(params, data, cb);
return this.oauthWithIDTokenValidation.create(params, data, cb);
}

return this.oauth.create(params, data);
return this.oauthWithIDTokenValidation.create(params, data);
};

/**
Expand Down Expand Up @@ -306,10 +310,10 @@ OAuthAuthenticator.prototype.authorizationCodeGrant = function(options, cb) {
}

if (cb && cb instanceof Function) {
return this.oauth.create(params, data, cb);
return this.oauthWithIDTokenValidation.create(params, data, cb);
}

return this.oauth.create(params, data);
return this.oauthWithIDTokenValidation.create(params, data);
};

module.exports = OAuthAuthenticator;
13 changes: 7 additions & 6 deletions src/auth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ var BASE_URL_FORMAT = 'https://%s';
* clientId: '{OPTIONAL_CLIENT_ID}'
* });
*
* @param {Object} options Options for the Authentication Client
* SDK.
* @param {String} options.domain AuthenticationClient server domain.
* @param {String} [options.clientId] Default client ID.
* @param {String} [options.clientSecret] Default client Secret.
* @param {Object} options Options for the Authentication Client SDK.
* @param {String} options.domain AuthenticationClient server domain.
* @param {String} [options.clientId] Default client ID.
* @param {String} [options.clientSecret] Default client Secret.
* @param {String} [options.supportedAlgorithms] Algorithms that your application expects to receive
*/
var AuthenticationClient = function(options) {
if (!options || typeof options !== 'object') {
Expand All @@ -62,7 +62,8 @@ var AuthenticationClient = function(options) {
'User-agent': 'node.js/' + process.version.replace('v', ''),
'Content-Type': 'application/json'
},
baseUrl: util.format(BASE_URL_FORMAT, options.domain)
baseUrl: util.format(BASE_URL_FORMAT, options.domain),
supportedAlgorithms: options.supportedAlgorithms
};

if (options.telemetry !== false) {
Expand Down
Loading

0 comments on commit 07ea7ae

Please sign in to comment.