Skip to content

Commit 23214dc

Browse files
committed
fix: validate requested scope on authorize request (#3)
1 parent 70159bd commit 23214dc

File tree

2 files changed

+71
-4
lines changed

2 files changed

+71
-4
lines changed

lib/handlers/authorize-handler.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,16 @@ AuthorizeHandler.prototype.handle = function(request, response) {
9797
var ResponseType;
9898

9999
return Promise.bind(this)
100-
.then(function() {
101-
scope = this.getScope(request);
100+
.then(function() {
101+
var requestedScope = this.getScope(request);
102102

103-
return this.generateAuthorizationCode(client, user, scope);
104-
})
103+
return this.validateScope(user, client, requestedScope);
104+
})
105+
.then(function(validScope) {
106+
scope = validScope;
107+
108+
return this.generateAuthorizationCode(client, user, scope);
109+
})
105110
.then(function(authorizationCode) {
106111
state = this.getState(request);
107112
ResponseType = this.getResponseType(request);
@@ -196,6 +201,24 @@ AuthorizeHandler.prototype.getClient = function(request) {
196201
});
197202
};
198203

204+
/**
205+
* Validate requested scope.
206+
*/
207+
AuthorizeHandler.prototype.validateScope = function(user, client, scope) {
208+
if (this.model.validateScope) {
209+
return promisify(this.model.validateScope, 3).call(this.model, user, client, scope)
210+
.then(function (scope) {
211+
if (!scope) {
212+
throw new InvalidScopeError('Invalid scope: Requested scope is invalid');
213+
}
214+
215+
return scope;
216+
});
217+
} else {
218+
return Promise.resolve(scope);
219+
}
220+
};
221+
199222
/**
200223
* Get scope from the request.
201224
*/

test/integration/handlers/authorize-handler_test.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,50 @@ describe('AuthorizeHandler integration', function() {
332332
});
333333
});
334334

335+
it('should redirect to an error response if `scope` is insufficient', function() {
336+
var client = { grants: ['authorization_code'], redirectUris: ['http://example.com/cb'] };
337+
var model = {
338+
getAccessToken: function() {
339+
return {
340+
client: client,
341+
user: {},
342+
accessTokenExpiresAt: new Date(new Date().getTime() + 10000)
343+
};
344+
},
345+
getClient: function() {
346+
return client;
347+
},
348+
saveAuthorizationCode: function() {
349+
return { authorizationCode: 12345, client: client };
350+
},
351+
validateScope: function() {
352+
return false;
353+
}
354+
};
355+
var handler = new AuthorizeHandler({ authorizationCodeLifetime: 120, model: model });
356+
var request = new Request({
357+
body: {
358+
client_id: 12345,
359+
response_type: 'code'
360+
},
361+
headers: {
362+
'Authorization': 'Bearer foo'
363+
},
364+
method: {},
365+
query: {
366+
scope: 'read',
367+
state: 'foobar'
368+
}
369+
});
370+
var response = new Response({ body: {}, headers: {} });
371+
372+
return handler.handle(request, response)
373+
.then(should.fail)
374+
.catch(function() {
375+
response.get('location').should.equal('http://example.com/cb?error=invalid_scope&error_description=Invalid%20scope%3A%20Requested%20scope%20is%20invalid');
376+
});
377+
});
378+
335379
it('should redirect to an error response if `state` is missing', function() {
336380
var model = {
337381
getAccessToken: function() {

0 commit comments

Comments
 (0)