Skip to content

Commit

Permalink
feat(grant): add Client Credentials Grant
Browse files Browse the repository at this point in the history
  • Loading branch information
mnovozhylov committed Jul 1, 2023
1 parent fc750f5 commit 7eaa70e
Show file tree
Hide file tree
Showing 8 changed files with 3,399 additions and 343 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Release History

## 2.2.0
* Add support of Client Credentials Grant
* Fix issue with "debug" config option

## 2.1.3
* Add GraphQL support

Expand Down
15 changes: 14 additions & 1 deletion example/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
var config = {
'clientId' : 'xxxxxxxx',
'clientSecret' : 'xxxxxxxx',
'redirectUri' : 'xxxxxxxx',
'redirectUri': 'xxxxxxxx',
// 'grantType' : 'client_credentials', // Required only for Client Credentials Grant
// 'accessToken' : 'xxxxxxxx', // assign if known
// 'refreshToken' : 'xxxxxxxx', // assign if known
// 'expiresIn' : '86399', // assign if known
Expand Down Expand Up @@ -43,6 +44,7 @@ var UpworkApi = require('node-upwork-oauth2') // use if package is installed via

// a function to get access/refresh token pair
function getAccessTokenPair(api, callback) {
// start Code Authorization Grant
debug('getting access/refresh token pair');
// get authorization url
var url = api.getAuthorizationUrl(config.redirectUri);
Expand All @@ -63,6 +65,17 @@ function getAccessTokenPair(api, callback) {
callback(accessToken);
});
});
// end Code Authorization Grant

// start Client Credentials Grant
// debug('getting access token pair');
// api.getToken("", function(error, accessToken) {
// if (error) throw new Error(error);

// debug(accessToken, 'got an access token');
// callback(accessToken);
// });
// end Client Credentials Grant
};

// get my data
Expand Down
6 changes: 3 additions & 3 deletions lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
* @requires debug, config, client
*/

debug = function(data, label) {
var d = new Debug(process.env.UPWORK_API_DEBUG || false);
d.log(data, label);
debug = function (data, label) {
var d = new Debug(process.env.UPWORK_API_DEBUG || false);
d.log(data, label);
}

var Debug = require('./debug')
Expand Down
59 changes: 44 additions & 15 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

debug('export client module');

const oauth2 = require('simple-oauth2');
const request = require('request');
const { ClientCredentials, AuthorizationCode } = require('simple-oauth2');

const UpworkLibraryUserAgent = 'Github Upwork API NodeJS Client';

Expand All @@ -35,24 +35,30 @@ function Client(config) {
this.entryPoint = undefined;
this.tenantId = undefined;

this.oauth2 = oauth2.create({
var oauth2Config = {
client: {
id: config.clientId,
secret: config.clientSecret
},
auth: {
tokenHost: config.tokenHost,
tokenPath: config.tokenPath,
authorizePath: config.authorizePath
},
http: {
headers: {
'User-Agent': UpworkLibraryUserAgent
},
}
});
};

debug(oauth2, 'got an oauth2 client');
if (this.config.grantType === 'client_credentials') {
this.simpleOauth2Client = new ClientCredentials(oauth2Config);
} else {
oauth2Config.auth['authorizePath'] = config.authorizePath;
this.simpleOauth2Client = new AuthorizationCode(oauth2Config);
}

debug(this.simpleOauth2Client, 'got an oauth2 client');
}

/**
Expand All @@ -63,7 +69,7 @@ function Client(config) {
Client.prototype.getAuthorizationUrl = function() {
debug(this.config.redirectUri, 'get authorization url with the specific request uri');

return this.oauth2.authorizationCode.authorizeURL({
return this.simpleOauth2Client.authorizeURL({
redirect_uri: this.config.redirectUri,
state: this.config.state
});
Expand All @@ -76,11 +82,26 @@ Client.prototype.getAuthorizationUrl = function() {
* @param authzCode {String} Authorization code
* @param callback
*/
Client.prototype.getToken = function(authzCode, callback) {
this.oauth2.authorizationCode.getToken({
code: authzCode,
redirect_uri: this.config.redirectUri
}, callback);
Client.prototype.getToken = async function(authzCode, callback) {
var accessToken;
var error;

try {
if (this.config.grantType == 'client_credentials') {
accessToken = await this.simpleOauth2Client.getToken();
} else {
accessToken = await this.simpleOauth2Client.getToken({
code: authzCode,
redirect_uri: this.config.redirectUri
});
}
debug(accessToken, 'Received an access token');
} catch (error) {
debug(error.message, 'Can not get valid Access Token');
debug(error, 'Error');
}

callback(error, accessToken);
}

/**
Expand All @@ -91,9 +112,9 @@ Client.prototype.getToken = function(authzCode, callback) {
* @param callback
* @async
*/
Client.prototype.setNewAccessTokenPair = function(tokenPair, callback) {
debug('setting access token from config');
let aToken = this.oauth2.accessToken.create(tokenPair);
Client.prototype.setNewAccessTokenPair = function (tokenPair, callback) {
debug(tokenPair, 'setting access token from token pair');
let aToken = this.simpleOauth2Client.createToken(tokenPair.token);

this.config.accessToken = aToken.token.access_token;
this.config.refreshToken = aToken.token.refresh_token;
Expand All @@ -109,7 +130,7 @@ Client.prototype.setNewAccessTokenPair = function(tokenPair, callback) {
*/
Client.prototype.setAccessToken = function(callback) {
debug('setting access token from config');
let aToken = this.oauth2.accessToken.create({
let aToken = this.simpleOauth2Client.createToken({
access_token: this.config.accessToken,
refresh_token: this.config.refreshToken,
expires_in: this.config.expiresIn,
Expand Down Expand Up @@ -262,7 +283,15 @@ Client.prototype.sendRequest = function (method, url, params, callback) {
_options.body = JSON.stringify(params);
}

debug(_options, 'Options for request');
debug(_params, 'Params for request');

request(Object.assign(_options, _params), (err, httpResponse, body) => {
if (err) {
debug(err, 'Request error');
debug(httpResponse, 'httpResponse');
debug(body, 'Body');
}
callback(err, httpResponse.statusCode, parseResponse(body));
});
}
Expand Down
7 changes: 6 additions & 1 deletion lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function Config(options) {
this.clientId = options.clientId;
this.clientSecret = options.clientSecret;
this.redirectUri = options.redirectUri;
this.grantType = options.grantType;
this.accessToken = options.accessToken;
this.refreshToken = options.refreshToken;
this.expiresIn = options.expiresIn;
Expand All @@ -30,9 +31,13 @@ function Config(options) {
this.debug = options.debug || false;
this.authorizePath = '/ab/account-security/oauth2/authorize';
this.tokenPath = '/api/v3/oauth2/token';
this.tokenHost = 'https://www.upwork.com';
this.tokenHost = 'https://stage.upwork.com';
this.baseUrl = this.tokenHost + '/api/';
this.gqlUrl = 'https://api.upwork.com/graphql';

if (this.debug) {
process.env.UPWORK_API_DEBUG = true;
}
}

module.exports = Config;
4 changes: 2 additions & 2 deletions lib/debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function Debug(mode) {
* @param data {String} Data to display
* @param [label=""] {String} Label
*/
Debug.prototype.log = function(data, label) {
Debug.prototype.log = function (data, label) {
if (this.mode == true || this.mode == 'true') {
if (typeof data == 'string' || data instanceof String) {
if (label) {
Expand All @@ -41,7 +41,7 @@ Debug.prototype.log = function(data, label) {
}
} else {
console.log(' >> start dump [' + label + '] >>');
console.log(' ' + data);
console.log(' ', data);
console.log(' >> end dump [' + label + '] >>');
}
}
Expand Down
Loading

0 comments on commit 7eaa70e

Please sign in to comment.