From b9cd14d9df10f41ebda4b9a8f4c42ce3a9e368af Mon Sep 17 00:00:00 2001 From: Basim Hennawi Date: Fri, 29 Dec 2017 15:04:11 +0100 Subject: [PATCH 1/2] Extend model object with request context --- lib/handlers/authenticate-handler.js | 3 +++ lib/handlers/authorize-handler.js | 3 +++ lib/handlers/token-handler.js | 3 +++ 3 files changed, 9 insertions(+) diff --git a/lib/handlers/authenticate-handler.js b/lib/handlers/authenticate-handler.js index dc9117b27..590c476a2 100644 --- a/lib/handlers/authenticate-handler.js +++ b/lib/handlers/authenticate-handler.js @@ -63,6 +63,9 @@ AuthenticateHandler.prototype.handle = function(request, response) { throw new InvalidArgumentError('Invalid argument: `response` must be an instance of Response'); } + // Extend model object with request + this.model.request = request; + return Promise.bind(this) .then(function() { return this.getTokenFromRequest(request); diff --git a/lib/handlers/authorize-handler.js b/lib/handlers/authorize-handler.js index 984136a8d..a86b36a11 100644 --- a/lib/handlers/authorize-handler.js +++ b/lib/handlers/authorize-handler.js @@ -82,6 +82,9 @@ AuthorizeHandler.prototype.handle = function(request, response) { return Promise.reject(new AccessDeniedError('Access denied: user denied access to application')); } + // Extend model object with request + this.model.request = request; + var fns = [ this.getAuthorizationCodeLifetime(), this.getClient(request), diff --git a/lib/handlers/token-handler.js b/lib/handlers/token-handler.js index feaad3f54..af162ca38 100644 --- a/lib/handlers/token-handler.js +++ b/lib/handlers/token-handler.js @@ -85,6 +85,9 @@ TokenHandler.prototype.handle = function(request, response) { return Promise.reject(new InvalidRequestError('Invalid request: content must be application/x-www-form-urlencoded')); } + // Extend model object with request + this.model.request = request; + return Promise.bind(this) .then(function() { return this.getClient(request, response); From cb7a559f1c432d136d6d1ab23482927230eead93 Mon Sep 17 00:00:00 2001 From: Basim Hennawi Date: Sun, 28 Jan 2018 15:31:26 +0100 Subject: [PATCH 2/2] Add unit and integration tests --- .../handlers/authenticate-handler_test.js | 3 +- .../handlers/authorize-handler_test.js | 3 +- .../handlers/token-handler_test.js | 3 +- .../handlers/authenticate-handler_test.js | 34 +++++++++++++++++ test/unit/handlers/authorize-handler_test.js | 34 +++++++++++++++++ test/unit/handlers/token-handler_test.js | 37 +++++++++++++++++++ 6 files changed, 111 insertions(+), 3 deletions(-) diff --git a/test/integration/handlers/authenticate-handler_test.js b/test/integration/handlers/authenticate-handler_test.js index 7852ea2eb..6ed227eaa 100644 --- a/test/integration/handlers/authenticate-handler_test.js +++ b/test/integration/handlers/authenticate-handler_test.js @@ -168,7 +168,7 @@ describe('AuthenticateHandler integration', function() { }); }); - it('should return an access token', function() { + it('should return an access token with extend model obj with request', function() { var accessToken = { user: {}, accessTokenExpiresAt: new Date(new Date().getTime() + 10000) @@ -192,6 +192,7 @@ describe('AuthenticateHandler integration', function() { return handler.handle(request, response) .then(function(data) { + model.request.should.equal(request); data.should.equal(accessToken); }) .catch(should.fail); diff --git a/test/integration/handlers/authorize-handler_test.js b/test/integration/handlers/authorize-handler_test.js index 0d1aa333b..03f40eb20 100644 --- a/test/integration/handlers/authorize-handler_test.js +++ b/test/integration/handlers/authorize-handler_test.js @@ -444,7 +444,7 @@ describe('AuthorizeHandler integration', function() { }); }); - it('should return the `code` if successful', function() { + it('should return the `code` if successful with extend model obj with request', function() { var client = { grants: ['authorization_code'], redirectUris: ['http://example.com/cb'] }; var model = { getAccessToken: function() { @@ -479,6 +479,7 @@ describe('AuthorizeHandler integration', function() { return handler.handle(request, response) .then(function(data) { + model.request.should.equal(request); data.should.eql({ authorizationCode: 12345, client: client diff --git a/test/integration/handlers/token-handler_test.js b/test/integration/handlers/token-handler_test.js index 50277c113..169ea12eb 100644 --- a/test/integration/handlers/token-handler_test.js +++ b/test/integration/handlers/token-handler_test.js @@ -297,7 +297,7 @@ describe('TokenHandler integration', function() { }); }); - it('should return a bearer token if successful', function() { + it('should return a bearer token if successful with extend model obj with request', function() { var token = { accessToken: 'foo', client: {}, refreshToken: 'bar', scope: 'foobar', user: {} }; var model = { getClient: function() { return { grants: ['password'] }; }, @@ -323,6 +323,7 @@ describe('TokenHandler integration', function() { return handler.handle(request, response) .then(function(data) { + model.request.should.equal(request); data.should.eql(token); }) .catch(should.fail); diff --git a/test/unit/handlers/authenticate-handler_test.js b/test/unit/handlers/authenticate-handler_test.js index 2adac7884..5c89f3d1f 100644 --- a/test/unit/handlers/authenticate-handler_test.js +++ b/test/unit/handlers/authenticate-handler_test.js @@ -6,6 +6,7 @@ var AuthenticateHandler = require('../../../lib/handlers/authenticate-handler'); var Request = require('../../../lib/request'); +var Response = require('../../../lib/response'); var sinon = require('sinon'); var should = require('should'); var ServerError = require('../../../lib/errors/server-error'); @@ -15,6 +16,39 @@ var ServerError = require('../../../lib/errors/server-error'); */ describe('AuthenticateHandler', function() { + describe('handle()', function() { + it('should extend model object with request context', function() { + var model = { + getAccessToken: sinon.stub().returns({ + user: 'foo', + accessTokenExpiresAt: new Date(new Date().getTime() + 10000) + }), + verifyScope: sinon.stub().returns(true) + }; + + var handler = new AuthenticateHandler({ + addAcceptedScopesHeader: true, + addAuthorizedScopesHeader: true, + model: model, + scope: 'bar' + }); + + var request = new Request({ + body: {}, + headers: { 'Authorization': 'Bearer foo' }, + method: {}, + query: {} + }); + var response = new Response({}); + + return handler.handle(request, response) + .then(function() { + model.request.should.equal(request); + }) + .catch(should.fail); + }); + }); + describe('getTokenFromRequest()', function() { describe('with bearer token in the request authorization header', function() { it('should call `getTokenFromRequestHeader()`', function() { diff --git a/test/unit/handlers/authorize-handler_test.js b/test/unit/handlers/authorize-handler_test.js index fe9b6b1d7..1f8ee0521 100644 --- a/test/unit/handlers/authorize-handler_test.js +++ b/test/unit/handlers/authorize-handler_test.js @@ -16,6 +16,40 @@ var should = require('should'); */ describe('AuthorizeHandler', function() { + describe('handle()', function() { + it('should extend model object with request context', function() { + var model = { + getClient: sinon.stub().returns({ + grants: ['authorization_code'], + redirectUris: ['/abc'] + }), + saveAuthorizationCode: sinon.stub().returns({ authorizationCode: 'code_abc' }) + }; + var handler = new AuthorizeHandler({ + authenticateHandler: { + handle: sinon.stub().returns({ name: 'xyz' }) + }, + authorizationCodeLifetime: 123, + allowEmptyState: true, + model: model + }); + + var request = new Request({ + body: { client_id: '123', response_type: 'code' }, + headers: {}, + method: {}, + query: {} + }); + var response = new Response({}); + + return handler.handle(request, response) + .then(function() { + model.request.should.equal(request); + }) + .catch(should.fail); + }); + }); + describe('generateAuthorizationCode()', function() { it('should call `model.generateAuthorizationCode()`', function() { var model = { diff --git a/test/unit/handlers/token-handler_test.js b/test/unit/handlers/token-handler_test.js index 2b37cd05a..1a0f7c735 100644 --- a/test/unit/handlers/token-handler_test.js +++ b/test/unit/handlers/token-handler_test.js @@ -5,6 +5,7 @@ */ var Request = require('../../../lib/request'); +var Response = require('../../../lib/response'); var TokenHandler = require('../../../lib/handlers/token-handler'); var sinon = require('sinon'); var should = require('should'); @@ -14,6 +15,42 @@ var should = require('should'); */ describe('TokenHandler', function() { + describe('handle()', function() { + it('should extend model object with request context', function() { + var model = { + getClient: sinon.stub().returns({ grants: ['client_credentials'] }), + getUserFromClient: sinon.stub().returns({}), + saveToken: sinon.stub().returns({ + accessToken: '123', + client: {}, + user: {}, + accessTokenExpiresAt: new Date(new Date().getTime() + 10000), + refreshTokenExpiresAt: new Date(new Date().getTime() + 10000) + }), + }; + + var handler = new TokenHandler({ + accessTokenLifetime: 123, + refreshTokenLifetime: 123, + model: model, + }); + + var request = new Request({ + method: 'POST', + body: { 'grant_type': 'client_credentials', 'client_id': 'abc', 'client_secret': 'xyz' }, + headers: { 'content-type': 'application/x-www-form-urlencoded', 'transfer-encoding': 'chunked' }, + query: {} + }); + var response = new Response({}); + + return handler.handle(request, response) + .then(function() { + model.request.should.equal(request); + }) + .catch(should.fail); + }); + }); + describe('getClient()', function() { it('should call `model.getClient()`', function() { var model = {