Skip to content
This repository was archived by the owner on Jan 20, 2024. It is now read-only.

Commit d11f883

Browse files
committed
Merge pull request #15 from mulesoft/global-options
Global options
2 parents 79172fa + fcce3cc commit d11f883

File tree

3 files changed

+52
-48
lines changed

3 files changed

+52
-48
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ token.request({
6363

6464
You can override the request mechanism if you need a custom implementation by setting `githubAuth.request = function (opts) { return new Promise(...) }`. You will need to make sure that the custom request mechanism supports the correct input and output objects.
6565

66+
**P.S.** All authorization methods accept `options` as the last argument, useful for overriding the global configuration on a per-request basis.
67+
6668
### [Authorization Code Grant](http://tools.ietf.org/html/rfc6749#section-4.1)
6769

6870
> The authorization code grant type is used to obtain both access tokens and refresh tokens and is optimized for confidential clients. Since this is a redirection-based flow, the client must be capable of interacting with the resource owner's user-agent (typically a web browser) and capable of receiving incoming requests (via redirection) from the authorization server.

client-oauth2.js

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ var extend = require('xtend')
22
var popsicle = require('popsicle')
33
var parseQuery = require('querystring').parse
44
var parseUrl = require('url').parse
5-
var omit = require('object.omit')
65

76
var btoa = typeof Buffer === 'function' ? btoaBuffer : window.btoa
87

@@ -200,6 +199,18 @@ function string (str) {
200199
return str == null ? '' : String(str)
201200
}
202201

202+
/**
203+
* Merge request options from an options object.
204+
*/
205+
function requestOptions (requestOptions, options) {
206+
return extend(requestOptions, {
207+
body: extend(options.body, requestOptions.body),
208+
query: extend(options.query, requestOptions.query),
209+
headers: extend(options.headers, requestOptions.headers),
210+
options: extend(options.options, requestOptions.options)
211+
})
212+
}
213+
203214
/**
204215
* Construct an object that can handle the multiple OAuth 2.0 flows.
205216
*
@@ -246,11 +257,11 @@ ClientOAuth2.prototype.createToken = function (access, refresh, type, data) {
246257
* Using the built-in request method, we'll automatically attempt to parse
247258
* the response.
248259
*
249-
* @param {Object} options
260+
* @param {Object} requestObject
250261
* @return {Promise}
251262
*/
252-
ClientOAuth2.prototype._request = function (options) {
253-
return this.request(this._requestOptions(options))
263+
ClientOAuth2.prototype._request = function (requestObject) {
264+
return this.request(requestObject)
254265
.then(function (res) {
255266
if (res.status < 200 || res.status >= 399) {
256267
var err = new Error('HTTP status ' + res.status)
@@ -263,15 +274,6 @@ ClientOAuth2.prototype._request = function (options) {
263274
})
264275
}
265276

266-
ClientOAuth2.prototype._requestOptions = function (options) {
267-
return extend(options, {
268-
body: extend(this.options.body, options.body),
269-
query: extend(this.options.query, options.query),
270-
headers: extend(this.options.headers, options.headers),
271-
options: extend(this.options.options, options.options)
272-
})
273-
}
274-
275277
/**
276278
* Set `popsicle` as the default request method.
277279
*/
@@ -285,12 +287,7 @@ ClientOAuth2.prototype.request = popsicle.request
285287
*/
286288
function ClientOAuth2Token (client, data) {
287289
this.client = client
288-
289-
this.data = omit(data, [
290-
'access_token', 'refresh_token', 'token_type', 'expires_in', 'scope',
291-
'state', 'error', 'error_description', 'error_uri'
292-
])
293-
290+
this.data = data
294291
this.tokenType = data.token_type && data.token_type.toLowerCase()
295292
this.accessToken = data.access_token
296293
this.refreshToken = data.refresh_token
@@ -318,60 +315,61 @@ ClientOAuth2Token.prototype.expiresIn = function (duration) {
318315
/**
319316
* Sign a standardised request object with user authentication information.
320317
*
321-
* @param {Object} opts
318+
* @param {Object} requestOptions
322319
* @return {Object}
323320
*/
324-
ClientOAuth2Token.prototype.sign = function (opts) {
321+
ClientOAuth2Token.prototype.sign = function (requestObject) {
325322
if (!this.accessToken) {
326323
throw new Error('Unable to sign without access token')
327324
}
328325

329-
opts.headers = opts.headers || {}
326+
requestObject.headers = requestObject.headers || {}
330327

331328
if (this.tokenType === 'bearer') {
332-
opts.headers.Authorization = 'Bearer ' + this.accessToken
329+
requestObject.headers.Authorization = 'Bearer ' + this.accessToken
333330
} else {
334-
var parts = opts.url.split('#')
331+
var parts = requestObject.url.split('#')
335332
var token = 'access_token=' + this.accessToken
336333
var url = parts[0].replace(/[?&]access_token=[^&#]/, '')
337334
var fragment = parts[1] ? '#' + parts[1] : ''
338335

339336
// Prepend the correct query string parameter to the url.
340-
opts.url = url + (url.indexOf('?') > -1 ? '&' : '?') + token + fragment
337+
requestObject.url = url + (url.indexOf('?') > -1 ? '&' : '?') + token + fragment
341338

342339
// Attempt to avoid storing the url in proxies, since the access token
343340
// is exposed in the query parameters.
344-
opts.headers.Pragma = 'no-store'
345-
opts.headers['Cache-Control'] = 'no-store'
341+
requestObject.headers.Pragma = 'no-store'
342+
requestObject.headers['Cache-Control'] = 'no-store'
346343
}
347344

348-
return opts
345+
return requestObject
349346
}
350347

351348
/**
352349
* Make a HTTP request as the user.
353350
*
354-
* @param {Object} opts
351+
* @param {Object} options
355352
* @return {Promise}
356353
*/
357-
ClientOAuth2Token.prototype.request = function (opts) {
358-
return this.client.request(this.client._requestOptions(this.sign(opts)))
354+
ClientOAuth2Token.prototype.request = function (options) {
355+
return this.client.request(requestOptions(this.sign(options), this.client.options))
359356
}
360357

361358
/**
362359
* Refresh a user access token with the supplied token.
363360
*
364361
* @return {Promise}
365362
*/
366-
ClientOAuth2Token.prototype.refresh = function () {
363+
ClientOAuth2Token.prototype.refresh = function (options) {
367364
var self = this
368-
var options = this.client.options
365+
366+
options = extend(this.client.options, options)
369367

370368
if (!this.refreshToken) {
371369
return Promise.reject(new Error('No refresh token set'))
372370
}
373371

374-
return this.client._request({
372+
return this.client._request(requestOptions({
375373
url: options.accessTokenUri,
376374
method: 'POST',
377375
headers: extend(DEFAULT_HEADERS, {
@@ -381,7 +379,7 @@ ClientOAuth2Token.prototype.refresh = function () {
381379
refresh_token: this.refreshToken,
382380
grant_type: 'refresh_token'
383381
}
384-
})
382+
}, options))
385383
.then(handleAuthResponse)
386384
.then(function (data) {
387385
self.accessToken = data.access_token
@@ -429,7 +427,7 @@ OwnerFlow.prototype.getToken = function (username, password, options) {
429427

430428
options = extend(this.client.options, options)
431429

432-
return this.client._request({
430+
return this.client._request(requestOptions({
433431
url: options.accessTokenUri,
434432
method: 'POST',
435433
headers: extend(DEFAULT_HEADERS, {
@@ -441,7 +439,7 @@ OwnerFlow.prototype.getToken = function (username, password, options) {
441439
password: password,
442440
grant_type: 'password'
443441
}
444-
})
442+
}, options))
445443
.then(handleAuthResponse)
446444
.then(function (data) {
447445
return new ClientOAuth2Token(self.client, data)
@@ -476,10 +474,11 @@ TokenFlow.prototype.getUri = function (options) {
476474
*
477475
* @param {String} uri
478476
* @param {String} [state]
477+
* @param {Object} [options]
479478
* @return {Promise}
480479
*/
481-
TokenFlow.prototype.getToken = function (uri, state) {
482-
var options = this.client.options
480+
TokenFlow.prototype.getToken = function (uri, state, options) {
481+
options = extend(this.client.options, options)
483482

484483
// Make sure the uri matches our expected redirect uri.
485484
if (uri.substr(0, options.redirectUri.length) !== options.redirectUri) {
@@ -546,7 +545,7 @@ CredentialsFlow.prototype.getToken = function (options) {
546545
'accessTokenUri'
547546
])
548547

549-
return this.client._request({
548+
return this.client._request(requestOptions({
550549
url: options.accessTokenUri,
551550
method: 'POST',
552551
headers: extend(DEFAULT_HEADERS, {
@@ -556,7 +555,7 @@ CredentialsFlow.prototype.getToken = function (options) {
556555
scope: sanitizeScope(options.scopes),
557556
grant_type: 'client_credentials'
558557
}
559-
})
558+
}, options))
560559
.then(handleAuthResponse)
561560
.then(function (data) {
562561
return new ClientOAuth2Token(self.client, data)
@@ -591,11 +590,13 @@ CodeFlow.prototype.getUri = function (options) {
591590
*
592591
* @param {String} uri
593592
* @param {String} [state]
593+
* @param {Object} [options]
594594
* @return {Promise}
595595
*/
596-
CodeFlow.prototype.getToken = function (uri, state) {
596+
CodeFlow.prototype.getToken = function (uri, state, options) {
597597
var self = this
598-
var options = this.client.options
598+
599+
options = extend(this.client.options, options)
599600

600601
expects(options, [
601602
'clientId',
@@ -631,7 +632,7 @@ CodeFlow.prototype.getToken = function (uri, state) {
631632
return Promise.reject(new Error('Missing code, unable to request token'))
632633
}
633634

634-
return this.client._request({
635+
return this.client._request(requestOptions({
635636
url: options.accessTokenUri,
636637
method: 'POST',
637638
headers: extend(DEFAULT_HEADERS),
@@ -642,7 +643,7 @@ CodeFlow.prototype.getToken = function (uri, state) {
642643
client_id: options.clientId,
643644
client_secret: options.clientSecret
644645
}
645-
})
646+
}, options))
646647
.then(handleAuthResponse)
647648
.then(function (data) {
648649
return new ClientOAuth2Token(self.client, data)
@@ -684,7 +685,7 @@ JwtBearerFlow.prototype.getToken = function (token, options) {
684685
headers['Authorization'] = auth(options.clientId, options.clientSecret)
685686
}
686687

687-
return this.client._request({
688+
return this.client._request(requestOptions({
688689
url: options.accessTokenUri,
689690
method: 'POST',
690691
headers: headers,
@@ -693,7 +694,7 @@ JwtBearerFlow.prototype.getToken = function (token, options) {
693694
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
694695
assertion: token
695696
}
696-
})
697+
}, options))
697698
.then(handleAuthResponse)
698699
.then(function (data) {
699700
return new ClientOAuth2Token(self.client, data)

test/user.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ describe('user', function () {
2626
expect(req.headers.Authorization).to.equal('Basic ' + btoa('abc:123'))
2727
expect(req.body.grant_type).to.equal('refresh_token')
2828
expect(req.body.refresh_token).to.equal(refreshToken)
29+
expect(req.body.test).to.equal(true)
2930

3031
return Promise.resolve({
3132
status: 200,
@@ -93,7 +94,7 @@ describe('user', function () {
9394
expect(user.accessToken).to.equal(accessToken)
9495
expect(user.tokenType).to.equal('bearer')
9596

96-
return user.refresh()
97+
return user.refresh({ body: { test: true } })
9798
.then(function (token) {
9899
expect(token).to.an.instanceOf(ClientOAuth2.Token)
99100
expect(token.accessToken).to.equal(refreshAccessToken)

0 commit comments

Comments
 (0)