Skip to content

Commit a950bc9

Browse files
committed
fix: authorization_code grant should not be required in implicit flow
This is a follow-up to #464 (implicit grant flow). It fixes a bug where the "authorization_code" grant was required in the client's "grant" array. However, for the implicit grant flow, only "implicit" grant should be required. Closes #520
1 parent c6a3137 commit a950bc9

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

lib/handlers/authorize-handler.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ AuthorizeHandler.prototype.getClient = function(request) {
147147
if (redirectUri && !is.uri(redirectUri)) {
148148
throw new InvalidRequestError('Invalid request: `redirect_uri` is not a valid URI');
149149
}
150+
150151
return promisify(this.model.getClient, 2).call(this.model, clientId, null)
151152
.then(function(client) {
152153
if (!client) {
@@ -157,7 +158,10 @@ AuthorizeHandler.prototype.getClient = function(request) {
157158
throw new InvalidClientError('Invalid client: missing client `grants`');
158159
}
159160

160-
if (!_.includes(client.grants, 'authorization_code')) {
161+
var responseType = request.body.response_type || request.query.response_type;
162+
var requestedGrantType = responseType === 'token' ? 'implicit' : 'authorization_code';
163+
164+
if (!_.includes(client.grants, requestedGrantType)) {
161165
throw new UnauthorizedClientError('Unauthorized client: `grant_type` is invalid');
162166
}
163167

@@ -168,6 +172,7 @@ AuthorizeHandler.prototype.getClient = function(request) {
168172
if (redirectUri && !_.includes(client.redirectUris, redirectUri)) {
169173
throw new InvalidClientError('Invalid client: `redirect_uri` does not match client value');
170174
}
175+
171176
return client;
172177
});
173178
};

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
{
3737
"name": "Jonathon Hill",
3838
"email": "jhill9693@gmail.com"
39+
},
40+
{
41+
"name": "Marco Lüthy",
42+
"email": "marco.luethy@gmail.com"
3943
}
4044
],
4145
"main": "index.js",

test/integration/handlers/authorize-handler_test.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,46 @@ describe('AuthorizeHandler integration', function() {
249249
.catch(should.fail);
250250
});
251251

252+
253+
it('given an implicit grant flow, should redirect to a successful response with `token` and `state` if successful', function() {
254+
var client = { grants: ['implicit'], redirectUris: ['http://example.com/cb'] };
255+
var token = { accessToken: 'foobar-token' }
256+
var model = {
257+
getAccessToken: function() {
258+
return {
259+
client: client,
260+
user: {},
261+
accessTokenExpiresAt: new Date(new Date().getTime() + 10000)
262+
};
263+
},
264+
getClient: function() {
265+
return client;
266+
},
267+
saveToken: function() { return token; }
268+
};
269+
var handler = new AuthorizeHandler({ accessTokenLifetime: 120, model: model });
270+
var request = new Request({
271+
body: {
272+
},
273+
headers: {
274+
'Authorization': 'Bearer foo'
275+
},
276+
method: {},
277+
query: {
278+
client_id: 12345,
279+
response_type: 'token',
280+
state: 'foobar'
281+
}
282+
});
283+
var response = new Response({ body: {}, headers: {} });
284+
285+
return handler.handle(request, response)
286+
.then(function() {
287+
response.get('location').should.equal('http://example.com/cb#access_token=foobar-token&state=foobar');
288+
})
289+
.catch(should.fail);
290+
});
291+
252292
it('should redirect to an error response if `scope` is invalid', function() {
253293
var model = {
254294
getAccessToken: function() {

0 commit comments

Comments
 (0)