mirror of
https://github.com/expo/node-auth0.git
synced 2026-11-15 08:58:07 -10:00
141 lines
3.9 KiB
JavaScript
141 lines
3.9 KiB
JavaScript
var request = require('request');
|
|
|
|
var api = require('./api');
|
|
var ApiError = require('./errors/ApiError');
|
|
|
|
function Client(options) {
|
|
|
|
var fieldsToValidate = !options.accessToken ?
|
|
['domain', 'clientID', 'clientSecret'] :
|
|
['domain'];
|
|
|
|
fieldsToValidate.forEach(function (k) {
|
|
if(!options[k]){
|
|
throw new Error(k + ' is required');
|
|
}
|
|
});
|
|
|
|
this.apiUrl = 'https://' + options.domain + '/api';
|
|
this.baseUrl = 'https://' + options.domain;
|
|
this.tokenUrl = 'https://' + options.domain + '/oauth/token';
|
|
this.api2Url = 'https://' + options.domain + '/api/v2';
|
|
this.options = options;
|
|
}
|
|
|
|
Client.getAccessToken = function (options, done) {
|
|
var body = {
|
|
'client_id': options.clientID,
|
|
'client_secret': options.clientSecret,
|
|
'grant_type': 'client_credentials'
|
|
};
|
|
|
|
if (options.audience) {
|
|
body.audience = options.audience;
|
|
}
|
|
|
|
var tokenUrl = 'https://' + options.domain + '/oauth/token';
|
|
|
|
request.post({
|
|
url: tokenUrl,
|
|
form: body
|
|
}, function (err, resp, body) {
|
|
|
|
if (err) return done(err);
|
|
if (resp.statusCode === 404) return done(new ApiError('unknown client', 404));
|
|
if (resp.statusCode.toString().substr(0, 1) !== '2') return done(new ApiError(body, resp.statusCode));
|
|
|
|
var accessToken = JSON.parse(body)['access_token'];
|
|
done(null, accessToken);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Gets user profile using a user's access token (not an app access token).
|
|
*
|
|
* @param {Object} options Which should contain:
|
|
* * userAccessToken: User's access token
|
|
* whose data is going to be fetched.
|
|
* * domain: Auth0 Tenant domain
|
|
* (ie. my-domain.auth0.com
|
|
* @param {function} cb Callback with signature function(err, profile)
|
|
*/
|
|
Client.getUserInfo = function(options, cb) {
|
|
if (!options || !options.userAccessToken || !options.domain) {
|
|
throw new Error('Options object should contain userAccessToken and ' +
|
|
'domain attributes');
|
|
}
|
|
var userInfoUrl = 'https://' + options.domain + '/userinfo';
|
|
|
|
var requestOptions = {
|
|
url: userInfoUrl + '?access_token=' + options.userAccessToken
|
|
};
|
|
|
|
request.get(requestOptions, function(err, res, data) {
|
|
if (err) {
|
|
return cb(err);
|
|
}
|
|
|
|
if (res.statusCode.toString().substr(0, 1) !== '2') {
|
|
return cb(new ApiError(data, res.statusCode));
|
|
}
|
|
|
|
try {
|
|
data = JSON.parse(data);
|
|
} catch (e) {
|
|
return cb(e);
|
|
}
|
|
|
|
return cb(null, data);
|
|
});
|
|
};
|
|
|
|
Client.prototype.getAccessToken = function(done){
|
|
var self = this;
|
|
|
|
if (this._currentAccessToken) return done(null, this._currentAccessToken);
|
|
|
|
return Client.getAccessToken(this.options, function (err, token) {
|
|
if (err) return done(err);
|
|
|
|
self._currentAccessToken = token;
|
|
|
|
var timer = setTimeout(function () {
|
|
delete self._currentAccessToken;
|
|
}, 1000 * 60 * 3); //~ 3 minutes
|
|
|
|
// unref method added in node 0.10.x
|
|
if (timer && timer.unref) {
|
|
// Make the timer active but if it's the only item left in the event loop
|
|
// won't keep the program running.
|
|
timer.unref();
|
|
}
|
|
|
|
// XXX: This is a workaround for node 0.8.x. (erase me when we
|
|
// drop support for that version).
|
|
// _accessTokenTimer is exposed so clients can do clearTimeout and
|
|
// make the process end (as unref is not present in node 0.8.x)
|
|
self._accessTokenTimer = timer;
|
|
|
|
done(null, token);
|
|
});
|
|
};
|
|
|
|
Object.keys(api).forEach(function (m) {
|
|
Client.prototype[m] = function (){
|
|
var args = [].slice.call(arguments);
|
|
var callback = args[args.length - 1];
|
|
|
|
if (this.options.accessToken) {
|
|
api[m].apply(this, [this.options.accessToken].concat(args));
|
|
}
|
|
else {
|
|
this.getAccessToken(function (err, accessToken) {
|
|
if (err) return callback(err);
|
|
api[m].apply(this, [accessToken].concat(args));
|
|
}.bind(this));
|
|
}
|
|
};
|
|
});
|
|
|
|
module.exports = Client;
|