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

Commit 58dd277

Browse files
authored
Handle authentication errors before status errors (#35)
1 parent c64edcd commit 58dd277

File tree

5 files changed

+44
-37
lines changed

5 files changed

+44
-37
lines changed

src/client-oauth2.js

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -107,30 +107,17 @@ function expects (obj, props) {
107107
* @param {Object} data
108108
* @return {String}
109109
*/
110-
function getAuthError (data) {
111-
var message = ERROR_RESPONSES[data.error] ||
112-
data.error ||
113-
data.error_message
114-
115-
// Return an error instance with the message if it exists.
116-
return message && new Error(message)
117-
}
118-
119-
/**
120-
* Handle the authentication response object.
121-
*
122-
* @param {Object} data
123-
* @return {Promise}
124-
*/
125-
function handleAuthResponse (data) {
126-
var err = getAuthError(data)
127-
128-
// If the response contains an error, reject the refresh token.
129-
if (err) {
130-
return Promise.reject(err)
110+
function getAuthError (body) {
111+
var message = ERROR_RESPONSES[body.error] ||
112+
body.error_description ||
113+
body.error
114+
115+
if (message) {
116+
var err = new Error(message)
117+
err.body = body
118+
err.code = 'EAUTH'
119+
return err
131120
}
132-
133-
return Promise.resolve(data)
134121
}
135122

136123
/**
@@ -277,13 +264,22 @@ ClientOAuth2.prototype._request = function (options) {
277264

278265
return this.request(options.method, url, body, options.headers)
279266
.then(function (res) {
267+
var body = parseResponseBody(res.body)
268+
var authErr = getAuthError(body)
269+
270+
if (authErr) {
271+
return Promise.reject(authErr)
272+
}
273+
280274
if (res.status < 200 || res.status >= 399) {
281-
var err = new Error('HTTP status ' + res.status)
282-
err.status = res.status
283-
err.body = parseResponseBody(res.body)
284-
return Promise.reject(err)
275+
var statusErr = new Error('HTTP status ' + res.status)
276+
statusErr.status = res.status
277+
statusErr.body = res.body
278+
statusErr.code = 'ESTATUS'
279+
return Promise.reject(statusErr)
285280
}
286-
return parseResponseBody(res.body)
281+
282+
return body
287283
})
288284
}
289285

@@ -378,7 +374,6 @@ ClientOAuth2Token.prototype.refresh = function (options) {
378374
grant_type: 'refresh_token'
379375
}
380376
}, options))
381-
.then(handleAuthResponse)
382377
.then(function (data) {
383378
return self.client.createToken(extend(self.data, data))
384379
})
@@ -433,7 +428,6 @@ OwnerFlow.prototype.getToken = function (username, password, options) {
433428
grant_type: 'password'
434429
}
435430
}, options))
436-
.then(handleAuthResponse)
437431
.then(function (data) {
438432
return self.client.createToken(data)
439433
})
@@ -548,7 +542,6 @@ CredentialsFlow.prototype.getToken = function (options) {
548542
grant_type: 'client_credentials'
549543
}
550544
}, options))
551-
.then(handleAuthResponse)
552545
.then(function (data) {
553546
return self.client.createToken(data)
554547
})
@@ -635,7 +628,6 @@ CodeFlow.prototype.getToken = function (uri, options) {
635628
client_secret: options.clientSecret
636629
}
637630
}, options))
638-
.then(handleAuthResponse)
639631
.then(function (data) {
640632
return self.client.createToken(data)
641633
})
@@ -686,7 +678,6 @@ JwtBearerFlow.prototype.getToken = function (token, options) {
686678
assertion: token
687679
}
688680
}, options))
689-
.then(handleAuthResponse)
690681
.then(function (data) {
691682
return self.client.createToken(data)
692683
})

test/code.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ describe('code', function () {
1212
accessTokenUri: config.accessTokenUri,
1313
authorizationUri: config.authorizationUri,
1414
authorizationGrants: ['code'],
15-
redirectUri: 'http://example.com/auth/callback',
15+
redirectUri: config.redirectUri,
1616
scopes: 'notifications'
1717
})
1818

@@ -36,6 +36,21 @@ describe('code', function () {
3636
})
3737
})
3838

39+
it('should reject with auth errors', function () {
40+
var errored = false
41+
42+
return githubAuth.code.getToken(config.redirectUri + '?error=invalid_request')
43+
.catch(function (err) {
44+
errored = true
45+
46+
expect(err.code).to.equal('EAUTH')
47+
expect(err.body.error).to.equal('invalid_request')
48+
})
49+
.then(function () {
50+
expect(errored).to.be.true
51+
})
52+
})
53+
3954
describe('#sign', function () {
4055
it('should be able to sign a standard request object', function () {
4156
return githubAuth.code.getToken(uri)

test/support/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
exports.accessTokenUri = 'http://localhost:' + process.env.PORT + '/login/oauth/access_token'
22
exports.authorizationUri = 'http://localhost:' + process.env.PORT + '/login/oauth/authorize'
3+
exports.redirectUri = 'http://example.com/auth/callback'
34

45
exports.accessToken = '4430eb16f4f6577c0f3a15fb6127cbf828a8e403'
56
exports.refreshToken = exports.accessToken.split('').reverse().join('')

test/token.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ var config = require('./support/config')
44
var ClientOAuth2 = require('../')
55

66
describe('token', function () {
7-
var uri = 'http://example.com/auth/callback#access_token=' + config.accessToken + '&token_type=bearer'
7+
var uri = config.redirectUri + '#access_token=' + config.accessToken + '&token_type=bearer'
88

99
var githubAuth = new ClientOAuth2({
1010
clientId: config.clientId,
1111
authorizationUri: config.authorizationUri,
1212
authorizationGrants: ['token'],
13-
redirectUri: 'http://example.com/auth/callback',
13+
redirectUri: config.redirectUri,
1414
scopes: ['notifications']
1515
})
1616

test/user.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe('user', function () {
1010
accessTokenUri: config.accessTokenUri,
1111
authorizationUri: config.authorizationUri,
1212
authorizationGrants: ['code'],
13-
redirectUri: 'http://example.com/auth/callback',
13+
redirectUri: config.redirectUri,
1414
scopes: 'notifications'
1515
})
1616

0 commit comments

Comments
 (0)