var test = require('tape'), errors = require('../../lib/errors'), url = require('url'), testError = 'boom!!!', pathToObjectUnderTest = '../../lib/authorizeRequest', authorizeRequest = require(pathToObjectUnderTest); function buildAuthorizationUri(context, expiresIn, code, token) { var redirect = url.parse(context.redirect_uri, true); delete redirect.search; if (context.scope) { redirect.query.scope = context.scope.join(','); } if (context.state) { redirect.query.state = context.state; } if (expiresIn) { redirect.query.expires_in = expiresIn; } if (code) { redirect.query.code = code; } if (token) { redirect.query.access_token = token; redirect.query.token_type = 'Bearer'; } return url.format(redirect); } test('authorizeRequest exists', function(t){ t.plan(2); t.ok(authorizeRequest, 'authorizeRequest Exists'); t.equal(typeof authorizeRequest, 'function', 'authorizeRequest is a function'); }); test('authorizeRequest errors with no context', function(t){ t.plan(2); var context = null, accountId = null; authorizeRequest(context, accountId, function(error){ t.ok(error, 'got error'); t.deepEqual(error, errors.invalidRequest(context), 'got correct error and data'); }); }); test('authorizeRequest errors with no context.response_type', function(t){ t.plan(2); var context = {}, accountId = null; authorizeRequest(context, accountId, function(error){ t.ok(error, 'got error'); t.deepEqual(error, errors.invalidRequest(context), 'got correct error and data'); }); }); test('authorizeRequest errors with invalid context.response_type', function(t){ t.plan(2); var context = { response_type: 'foo' }, accountId = null; authorizeRequest(context, accountId, function(error){ t.ok(error, 'got error'); t.deepEqual(error, errors.unsupportedResponseType(context), 'got correct error and data'); }); }); test('authorizeRequest continues with valid context.response_type', function(t){ t.plan(4); var context = { response_type: 'token' }, accountId = null, authServer = { isSupportedScope: function(){ return false; } }; authorizeRequest.call(authServer, context, accountId, function(error){ t.ok(error, 'got error'); t.notDeepEqual(error, errors.unsupportedResponseType(context), 'got correct error and data'); }); context.response_type = 'code'; authorizeRequest.call(authServer, context, accountId, function(error){ t.ok(error, 'got error'); t.notDeepEqual(error, errors.unsupportedResponseType(context), 'got correct error and data'); }); }); test('authorizeRequest errors with invalid context.scope', function(t){ t.plan(3); var context = { response_type: 'token', scope: 'foo' }, accountId = null, authServer = { isSupportedScope: function(scope){ t.equal(scope, context.scope, 'got correct scope'); return false; } }; authorizeRequest.call(authServer, context, accountId, function(error){ t.ok(error, 'got error'); t.deepEqual(error, errors.invalidScope(context), 'got correct error and data'); }); }); test('authorizeRequest handels getByIdErrors', function(t){ t.plan(3); var context = { response_type: 'token', client_id: 123 }, accountId = null, authServer = { isSupportedScope: function(){ return true; }, clientService: { getById: function(clientId, callback){ t.equal(clientId, context.client_id, 'got correct clientId'); callback(testError); } } }; authorizeRequest.call(authServer, context, accountId, function(error){ t.ok(error, 'got error'); t.equal(error, testError, 'got correct error and data'); }); }); test('authorizeRequestWithClient requires client', function(t){ t.plan(2); var context = { response_type: 'token', client_id: 123 }, accountId = null, authServer = { isSupportedScope: function(){ return true; }, clientService: { getById: function(clientId, callback){ callback(); } } }; authorizeRequest.call(authServer, context, accountId, function(error){ t.ok(error, 'got error'); t.deepEqual(error, errors.invalidClient(context), 'got correct error and data'); }); }); test('authorizeRequestWithClient requires context.redirect_uri', function(t){ t.plan(2); var context = { response_type: 'token', client_id: 123 }, accountId = null, testClient = {}, authServer = { isSupportedScope: function(){ return true; }, clientService: { getById: function(clientId, callback){ callback(null, testClient); } } }; authorizeRequest.call(authServer, context, accountId, function(error){ t.ok(error, 'got error'); t.deepEqual(error, errors.redirectUriMismatch(context), 'got correct error and data'); }); }); test('authorizeRequestWithClient errors on redirect_uri mismatch', function(t){ t.plan(4); var context = { response_type: 'token', redirect_uri: 'foo' }, accountId = null, testClient = {}, authServer = { isSupportedScope: function(){ return true; }, clientService: { getById: function(clientId, callback){ callback(null, testClient); }, isValidRedirectUri: function(client, redirectUri){ t.equal(client, testClient, 'got correct client'); t.equal(redirectUri, context.redirect_uri, 'got correct redirect_uri'); return false; } } }; authorizeRequest.call(authServer, context, accountId, function(error){ t.ok(error, 'got error'); t.deepEqual(error, errors.redirectUriMismatch(context), 'got correct error and data'); }); }); test('authorizeRequestWithClient generate code if response_type is code', function(t){ t.plan(6); var now = new Date(), context = { response_type: 'code', redirect_uri: 'http://foo.com/?things=stuff', scope: ['things', 'stuff'], state: 'foo' }, accountId = 123, testClient = { id: 789 }, generatedCode = 'generated code', expectedCodeData = { code: generatedCode, redirectUri: context.redirect_uri, clientId: testClient.id, expiresDate: now, accountId: accountId }, authServer = { isSupportedScope: function(){ return true; }, getExpiresDate: function(){ return now; }, expiresIn: 1234, clientService: { getById: function(clientId, callback){ callback(null, testClient); }, isValidRedirectUri: function(client, redirectUri){ t.equal(client, testClient, 'got correct client'); t.equal(redirectUri, context.redirect_uri, 'got correct redirect_uri'); return true; } }, tokenService: { generateAuthorizationCode: function(callback){ t.pass('generated code'); callback(null, generatedCode); } }, authorizationService: { saveAuthorizationCode: function(codeData, callback){ t.deepEqual(codeData, expectedCodeData, 'created code with correct data'); callback(null, expectedCodeData); } } }, expectedResult = { redirectUri: buildAuthorizationUri(context, authServer.expiresIn, expectedCodeData.code), state: context }; authorizeRequest.call(authServer, context, accountId, function(error, result){ t.notOk(error, 'no error'); t.deepEqual(result, expectedResult, 'got correct result'); }); }); test('authorizeRequestWithClient generate code handels save code error', function(t){ t.plan(2); var now = new Date(), context = { response_type: 'code', redirect_uri: 'http://foo.com/?things=stuff' }, accountId = 123, testClient = { id: 789 }, generatedCode = 'generated code', authServer = { isSupportedScope: function(){ return true; }, getExpiresDate: function(){ return now; }, expiresIn: 1234, clientService: { getById: function(clientId, callback){ callback(null, testClient); }, isValidRedirectUri: function(){ return true; } }, tokenService: { generateAuthorizationCode: function(callback){ callback(null, generatedCode); } }, authorizationService: { saveAuthorizationCode: function(codeData, callback){ callback(testError); } } }; authorizeRequest.call(authServer, context, accountId, function(error){ t.ok(error, 'no error'); t.equal(error, testError, 'got correct error'); }); }); test('authorizeRequestWithClient generate code handels generate code error', function(t){ t.plan(2); var now = new Date(), context = { response_type: 'code', redirect_uri: 'http://foo.com/?things=stuff' }, accountId = 123, testClient = { id: 789 }, authServer = { isSupportedScope: function(){ return true; }, getExpiresDate: function(){ return now; }, expiresIn: 1234, clientService: { getById: function(clientId, callback){ callback(null, testClient); }, isValidRedirectUri: function(){ return true; } }, tokenService: { generateAuthorizationCode: function(callback){ callback(testError); } } }; authorizeRequest.call(authServer, context, accountId, function(error){ t.ok(error, 'no error'); t.equal(error, testError, 'got correct error'); }); }); test('authorizeRequestWithClient generate code handels get client error', function(t){ t.plan(2); var now = new Date(), context = { response_type: 'code', redirect_uri: 'http://foo.com/?things=stuff' }, accountId = 123, authServer = { isSupportedScope: function(){ return true; }, getExpiresDate: function(){ return now; }, expiresIn: 1234, clientService: { getById: function(clientId, callback){ callback(testError); } } }; authorizeRequest.call(authServer, context, accountId, function(error){ t.ok(error, 'no error'); t.equal(error, testError, 'got correct error'); }); }); test('authorizeRequestWithClient generate token if response_type is token', function(t){ t.plan(6); var now = new Date(), context = { response_type: 'token', redirect_uri: 'http://foo.com/?things=stuff', scope: ['things', 'stuff'], state: 'foo' }, accountId = 123, testClient = { id: 789 }, generatedToken = 'generated token', expectedTokenData = { clientId: testClient.id, access_token: generatedToken, expires_in: now, accountId: accountId, token_type: 'Bearer' }, authServer = { isSupportedScope: function(){ return true; }, getExpiresDate: function(){ return now; }, expiresIn: 1234, clientService: { getById: function(clientId, callback){ callback(null, testClient); }, isValidRedirectUri: function(client, redirectUri){ t.equal(client, testClient, 'got correct client'); t.equal(redirectUri, context.redirect_uri, 'got correct redirect_uri'); return true; } }, tokenService: { generateToken: function(callback){ t.pass('generated token'); callback(null, generatedToken); } }, authorizationService: { saveAccessToken: function(tokenData, callback){ t.deepEqual(tokenData, expectedTokenData, 'created token with correct data'); callback(null, expectedTokenData); } } }, expectedResult = { redirectUri: buildAuthorizationUri(context, authServer.expiresIn, undefined, expectedTokenData.access_token), state: context }; authorizeRequest.call(authServer, context, accountId, function(error, result){ t.notOk(error, 'no error'); t.deepEqual(result, expectedResult, 'got correct result'); }); }); test('authorizeRequestWithClient generate token handels save token error', function(t){ t.plan(2); var now = new Date(), context = { response_type: 'token', redirect_uri: 'http://foo.com/?things=stuff' }, accountId = 123, testClient = { id: 789 }, generatedToken = 'generated token', authServer = { isSupportedScope: function(){ return true; }, getExpiresDate: function(){ return now; }, expiresIn: 1234, clientService: { getById: function(clientId, callback){ callback(null, testClient); }, isValidRedirectUri: function(){ return true; } }, tokenService: { generateToken: function(callback){ callback(null, generatedToken); } }, authorizationService: { saveAccessToken: function(tokenData, callback){ callback(testError); } } }; authorizeRequest.call(authServer, context, accountId, function(error){ t.ok(error, 'no error'); t.equal(error, testError, 'got correct error'); }); }); test('authorizeRequestWithClient generate token handels generate token error', function(t){ t.plan(2); var now = new Date(), context = { response_type: 'token', redirect_uri: 'http://foo.com/?things=stuff' }, accountId = 123, testClient = { id: 789 }, authServer = { isSupportedScope: function(){ return true; }, getExpiresDate: function(){ return now; }, expiresIn: 1234, clientService: { getById: function(clientId, callback){ callback(null, testClient); }, isValidRedirectUri: function(){ return true; } }, tokenService: { generateToken: function(callback){ callback(testError); } } }; authorizeRequest.call(authServer, context, accountId, function(error){ t.ok(error, 'no error'); t.equal(error, testError, 'got correct error'); }); });