diff --git a/lib/exchange/authorizationCode.js b/lib/exchange/authorizationCode.js index 4ee580c2..4040849e 100644 --- a/lib/exchange/authorizationCode.js +++ b/lib/exchange/authorizationCode.js @@ -61,22 +61,22 @@ module.exports = function(options, issue) { options = undefined; } options = options || {}; - + if (!issue) { throw new TypeError('oauth2orize.authorizationCode exchange requires an issue callback'); } - + var userProperty = options.userProperty || 'user'; return function authorization_code(req, res, next) { if (!req.body) { return next(new Error('OAuth2orize requires body parsing. Did you forget app.use(express.bodyParser())?')); } - + // The 'user' property of `req` holds the authenticated user. In the case // of the token endpoint, the property will contain the OAuth 2.0 client. var client = req[userProperty] , code = req.body.code , redirectURI = req.body.redirect_uri; - + if (!code) { return next(new TokenError('Missing required parameter: code', 'invalid_request')); } - + function issued(err, accessToken, refreshToken, params) { if (err) { return next(err); } if (!accessToken) { return next(new TokenError('Invalid authorization code', 'invalid_grant')); } @@ -97,10 +97,12 @@ module.exports = function(options, issue) { res.setHeader('Pragma', 'no-cache'); res.end(json); } - + try { var arity = issue.length; - if (arity == 5) { + if (arity == 6) { + issue(client, code, redirectURI, req.body, req.headers, issued); + } else if (arity == 5) { issue(client, code, redirectURI, req.body, issued); } else { // arity == 4 issue(client, code, redirectURI, issued); diff --git a/lib/exchange/clientCredentials.js b/lib/exchange/clientCredentials.js index 648815ed..98dc4e26 100644 --- a/lib/exchange/clientCredentials.js +++ b/lib/exchange/clientCredentials.js @@ -60,7 +60,7 @@ module.exports = function(options, issue) { options = undefined; } options = options || {}; - + if (!issue) { throw new TypeError('oauth2orize.clientCredentials exchange requires an issue callback'); } var userProperty = options.userProperty || 'user'; @@ -77,12 +77,12 @@ module.exports = function(options, issue) { return function client_credentials(req, res, next) { if (!req.body) { return next(new Error('OAuth2orize requires body parsing. Did you forget app.use(express.bodyParser())?')); } - + // The 'user' property of `req` holds the authenticated user. In the case // of the token endpoint, the property will contain the OAuth 2.0 client. var client = req[userProperty] , scope = req.body.scope; - + if (scope) { for (var i = 0, len = separators.length; i < len; i++) { var separated = scope.split(separators[i]); @@ -95,7 +95,7 @@ module.exports = function(options, issue) { } if (!Array.isArray(scope)) { scope = [ scope ]; } } - + function issued(err, accessToken, refreshToken, params) { if (err) { return next(err); } if (!accessToken) { return next(new TokenError('Invalid client credentials', 'invalid_grant')); } @@ -109,17 +109,19 @@ module.exports = function(options, issue) { if (refreshToken) { tok.refresh_token = refreshToken; } if (params) { utils.merge(tok, params); } tok.token_type = tok.token_type || 'Bearer'; - + var json = JSON.stringify(tok); res.setHeader('Content-Type', 'application/json'); res.setHeader('Cache-Control', 'no-store'); res.setHeader('Pragma', 'no-cache'); res.end(json); } - + try { var arity = issue.length; - if (arity == 4) { + if (arity == 5) { + issue(client, scope, req.body, req.headers, issued); + } else if (arity == 4) { issue(client, scope, req.body, issued); } else if (arity == 3) { issue(client, scope, issued); diff --git a/lib/exchange/password.js b/lib/exchange/password.js index e2d91b7f..247eaaf3 100644 --- a/lib/exchange/password.js +++ b/lib/exchange/password.js @@ -78,17 +78,17 @@ module.exports = function(options, issue) { return function password(req, res, next) { if (!req.body) { return next(new Error('OAuth2orize requires body parsing. Did you forget app.use(express.bodyParser())?')); } - + // The 'user' property of `req` holds the authenticated user. In the case // of the token endpoint, the property will contain the OAuth 2.0 client. var client = req[userProperty] , username = req.body.username , passwd = req.body.password , scope = req.body.scope; - + if (!username) { return next(new TokenError('Missing required parameter: username', 'invalid_request')); } if (!passwd) { return next(new TokenError('Missing required parameter: password', 'invalid_request')); } - + if (scope) { for (var i = 0, len = separators.length; i < len; i++) { var separated = scope.split(separators[i]); @@ -101,7 +101,7 @@ module.exports = function(options, issue) { } if (!Array.isArray(scope)) { scope = [ scope ]; } } - + function issued(err, accessToken, refreshToken, params) { if (err) { return next(err); } if (!accessToken) { return next(new TokenError('Invalid resource owner credentials', 'invalid_grant')); } @@ -109,23 +109,25 @@ module.exports = function(options, issue) { params = refreshToken; refreshToken = null; } - + var tok = {}; tok.access_token = accessToken; if (refreshToken) { tok.refresh_token = refreshToken; } if (params) { utils.merge(tok, params); } tok.token_type = tok.token_type || 'Bearer'; - + var json = JSON.stringify(tok); res.setHeader('Content-Type', 'application/json'); res.setHeader('Cache-Control', 'no-store'); res.setHeader('Pragma', 'no-cache'); res.end(json); } - + try { var arity = issue.length; - if (arity == 6) { + if (arity == 7) { + issue(client, username, passwd, scope, req.body, req.headers, issued); + } else if (arity == 6) { issue(client, username, passwd, scope, req.body, issued); } else if (arity == 5) { issue(client, username, passwd, scope, issued); diff --git a/lib/exchange/refreshToken.js b/lib/exchange/refreshToken.js index 616c097d..2753c36b 100644 --- a/lib/exchange/refreshToken.js +++ b/lib/exchange/refreshToken.js @@ -58,9 +58,9 @@ module.exports = function(options, issue) { options = undefined; } options = options || {}; - + if (!issue) { throw new TypeError('oauth2orize.refreshToken exchange requires an issue callback'); } - + var userProperty = options.userProperty || 'user'; // For maximum flexibility, multiple scope spearators can optionally be @@ -75,15 +75,15 @@ module.exports = function(options, issue) { return function refresh_token(req, res, next) { if (!req.body) { return next(new Error('OAuth2orize requires body parsing. Did you forget app.use(express.bodyParser())?')); } - + // The 'user' property of `req` holds the authenticated user. In the case // of the token endpoint, the property will contain the OAuth 2.0 client. var client = req[userProperty] , refreshToken = req.body.refresh_token , scope = req.body.scope; - + if (!refreshToken) { return next(new TokenError('Missing required parameter: refresh_token', 'invalid_request')); } - + if (scope) { for (var i = 0, len = separators.length; i < len; i++) { var separated = scope.split(separators[i]); @@ -96,7 +96,7 @@ module.exports = function(options, issue) { } if (!Array.isArray(scope)) { scope = [ scope ]; } } - + function issued(err, accessToken, refreshToken, params) { if (err) { return next(err); } if (!accessToken) { return next(new TokenError('Invalid refresh token', 'invalid_grant')); } @@ -104,23 +104,27 @@ module.exports = function(options, issue) { params = refreshToken; refreshToken = null; } - + var tok = {}; tok.access_token = accessToken; if (refreshToken) { tok.refresh_token = refreshToken; } if (params) { utils.merge(tok, params); } tok.token_type = tok.token_type || 'Bearer'; - + var json = JSON.stringify(tok); res.setHeader('Content-Type', 'application/json'); res.setHeader('Cache-Control', 'no-store'); res.setHeader('Pragma', 'no-cache'); res.end(json); } - + try { var arity = issue.length; - if (arity == 4) { + if (arity == 6) { + issue(client, refreshToken, scope, req.body, req.headers, issued); + } else if (arity == 5) { + issue(client, refreshToken, scope, req.body, issued); + } else if (arity == 4) { issue(client, refreshToken, scope, issued); } else { // arity == 3 issue(client, refreshToken, issued); diff --git a/test/exchange/authorizationCode.test.js b/test/exchange/authorizationCode.test.js index 6ba4245c..2fca49de 100644 --- a/test/exchange/authorizationCode.test.js +++ b/test/exchange/authorizationCode.test.js @@ -3,7 +3,7 @@ var chai = require('chai') describe('exchange.authorizationCode', function() { - + function issue(client, code, redirectURI, done) { if (client.id == 'c123' && code == 'abc123' && redirectURI == 'http://example.com/oa/callback') { return done(null, 's3cr1t'); @@ -22,17 +22,17 @@ describe('exchange.authorizationCode', function() { } return done(new Error('something is wrong')); } - + it('should be named authorization_code', function() { expect(authorizationCode(function(){}).name).to.equal('authorization_code'); }); - + it('should throw if constructed without a issue callback', function() { expect(function() { authorizationCode(); }).to.throw(TypeError, 'oauth2orize.authorizationCode exchange requires an issue callback'); }); - + describe('issuing an access token', function() { var response, err; @@ -48,18 +48,18 @@ describe('exchange.authorizationCode', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('issuing an access token and refresh token', function() { var response, err; @@ -75,18 +75,18 @@ describe('exchange.authorizationCode', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","refresh_token":"getANotehr","token_type":"Bearer"}'); }); }); - + describe('issuing an access token and params', function() { var response, err; @@ -102,18 +102,18 @@ describe('exchange.authorizationCode', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","expires_in":3600,"token_type":"Bearer"}'); }); }); - + describe('issuing an access token, null refresh token, and params', function() { var response, err; @@ -129,18 +129,18 @@ describe('exchange.authorizationCode', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","expires_in":3600,"token_type":"Bearer"}'); }); }); - + describe('issuing an access token, refresh token, and params with token_type', function() { var response, err; @@ -156,21 +156,21 @@ describe('exchange.authorizationCode', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","refresh_token":"blahblag","token_type":"foo","expires_in":3600}'); }); }); - + describe('issuing an access token based on body', function() { var response, err; - + function issue(client, code, redirectURI, body, done) { if (client.id == 'c123' && code == 'abc123' && redirectURI == 'http://example.com/oa/callback' && body.code_verifier == 's3cr1t') { return done(null, 's3cr1t'); @@ -190,18 +190,54 @@ describe('exchange.authorizationCode', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + + describe('issuing an access token based on body with access to headers', function() { + var response, err; + + function issue(client, code, redirectURI, body, headers, done) { + if (client.id == 'c123' && code == 'abc123' + && redirectURI == 'http://example.com/oa/callback' + && body.code_verifier == 's3cr1t' && headers != null) { + return done(null, 's3cr1t'); + } + return done(new Error('something is wrong')); + } + + before(function(done) { + chai.connect.use(authorizationCode(issue)) + .req(function(req) { + req.user = { id: 'c123', name: 'Example' }; + req.body = { code: 'abc123', redirect_uri: 'http://example.com/oa/callback', code_verifier: 's3cr1t' }; + }) + .end(function(res) { + response = res; + done(); + }) + .dispatch(); + }); + + it('should respond with headers', function() { + expect(response.getHeader('Content-Type')).to.equal('application/json'); + expect(response.getHeader('Cache-Control')).to.equal('no-store'); + expect(response.getHeader('Pragma')).to.equal('no-cache'); + }); + + it('should respond with body', function() { + expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); + }); + }); + describe('not issuing an access token', function() { var response, err; @@ -217,7 +253,7 @@ describe('exchange.authorizationCode', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.constructor.name).to.equal('TokenError'); @@ -226,7 +262,7 @@ describe('exchange.authorizationCode', function() { expect(err.status).to.equal(403); }); }); - + describe('handling a request without code parameter', function() { var response, err; @@ -242,7 +278,7 @@ describe('exchange.authorizationCode', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.constructor.name).to.equal('TokenError'); @@ -251,7 +287,7 @@ describe('exchange.authorizationCode', function() { expect(err.status).to.equal(400); }); }); - + describe('encountering an error while issuing an access token', function() { var response, err; @@ -267,13 +303,13 @@ describe('exchange.authorizationCode', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.message).to.equal('something is wrong'); }); }); - + describe('encountering an exception while issuing an access token', function() { var response, err; @@ -289,13 +325,13 @@ describe('exchange.authorizationCode', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.message).to.equal('something was thrown'); }); }); - + describe('handling a request without a body', function() { var response, err; @@ -310,13 +346,13 @@ describe('exchange.authorizationCode', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.message).to.equal('OAuth2orize requires body parsing. Did you forget app.use(express.bodyParser())?'); }); }); - + describe('with user property option issuing an access token', function() { var response, err; @@ -332,16 +368,16 @@ describe('exchange.authorizationCode', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + }); diff --git a/test/exchange/clientCredentials.test.js b/test/exchange/clientCredentials.test.js index 3c6bf9e5..9b23546b 100644 --- a/test/exchange/clientCredentials.test.js +++ b/test/exchange/clientCredentials.test.js @@ -3,7 +3,7 @@ var chai = require('chai') describe('exchange.clientCredentials', function() { - + function issue(client, done) { if (client.id == 'c123') { return done(null, 's3cr1t') @@ -22,17 +22,17 @@ describe('exchange.clientCredentials', function() { } return done(new Error('something is wrong')); } - + it('should be named client_credentials', function() { expect(clientCredentials(function(){}).name).to.equal('client_credentials'); }); - + it('should throw if constructed without a issue callback', function() { expect(function() { clientCredentials(); }).to.throw(TypeError, 'oauth2orize.clientCredentials exchange requires an issue callback'); }); - + describe('issuing an access token', function() { var response, err; @@ -48,18 +48,18 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('issuing an access token and refresh token', function() { var response, err; @@ -75,18 +75,18 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","refresh_token":"getANotehr","token_type":"Bearer"}'); }); }); - + describe('issuing an access token and params', function() { var response, err; @@ -102,18 +102,18 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","expires_in":3600,"token_type":"Bearer"}'); }); }); - + describe('issuing an access token, null refresh token, and params', function() { var response, err; @@ -129,18 +129,18 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","expires_in":3600,"token_type":"Bearer"}'); }); }); - + describe('issuing an access token, refresh token, and params with token_type', function() { var response, err; @@ -156,18 +156,18 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","refresh_token":"blahblag","token_type":"foo","expires_in":3600}'); }); }); - + describe('issuing an access token based on scope', function() { function issue(client, scope, done) { if (client.id == 'c123' && scope.length == 1 && scope[0] == 'read') { @@ -175,7 +175,7 @@ describe('exchange.clientCredentials', function() { } return done(new Error('something is wrong')); } - + var response, err; before(function(done) { @@ -190,18 +190,18 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('issuing an access token based on scope and body', function() { function issue(client, scope, body, done) { if (client.id == 'c123' && scope.length == 1 && scope[0] == 'read' && body.audience == 'https://www.example.com/') { @@ -209,7 +209,42 @@ describe('exchange.clientCredentials', function() { } return done(new Error('something is wrong')); } - + + var response, err; + + before(function(done) { + chai.connect.use(clientCredentials(issue)) + .req(function(req) { + req.user = { id: 'c123', name: 'Example' }; + req.body = { scope: 'read', audience: 'https://www.example.com/' }; + }) + .end(function(res) { + response = res; + done(); + }) + .dispatch(); + }); + + it('should respond with headers', function() { + expect(response.getHeader('Content-Type')).to.equal('application/json'); + expect(response.getHeader('Cache-Control')).to.equal('no-store'); + expect(response.getHeader('Pragma')).to.equal('no-cache'); + }); + + it('should respond with body', function() { + expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); + }); + }); + + describe('issuing an access token based on scope and body with access to headers', function() { + function issue(client, scope, body, headers, done) { + if (client.id == 'c123' && scope.length == 1 && scope[0] == 'read' + && body.audience == 'https://www.example.com/' && headers != null) { + return done(null, 's3cr1t') + } + return done(new Error('something is wrong')); + } + var response, err; before(function(done) { @@ -224,18 +259,18 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('issuing an access token based on array of scopes', function() { function issue(client, scope, done) { if (client.id == 'c123' && scope.length == 2 && scope[0] == 'read' && scope[1] == 'write') { @@ -243,7 +278,7 @@ describe('exchange.clientCredentials', function() { } return done(new Error('something is wrong')); } - + var response, err; before(function(done) { @@ -258,18 +293,18 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('not issuing an access token', function() { var response, err; @@ -285,7 +320,7 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.constructor.name).to.equal('TokenError'); @@ -294,7 +329,7 @@ describe('exchange.clientCredentials', function() { expect(err.status).to.equal(403); }); }); - + describe('encountering an error while issuing an access token', function() { var response, err; @@ -310,13 +345,13 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.message).to.equal('something is wrong'); }); }); - + describe('encountering an exception while issuing an access token', function() { var response, err; @@ -332,13 +367,13 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.message).to.equal('something was thrown'); }); }); - + describe('handling a request without a body', function() { var response, err; @@ -353,13 +388,13 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.message).to.equal('OAuth2orize requires body parsing. Did you forget app.use(express.bodyParser())?'); }); }); - + describe('with scope separator option', function() { function issue(client, scope, done) { if (client.id == 'c123' && scope.length == 2 && scope[0] == 'read' && scope[1] == 'write') { @@ -367,7 +402,7 @@ describe('exchange.clientCredentials', function() { } return done(new Error('something is wrong')); } - + describe('issuing an access token based on scope', function() { var response, err; @@ -383,19 +418,19 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); }); - + describe('with multiple scope separator option', function() { function issue(client, scope, done) { if (client.id == 'c123' && scope.length == 2 && scope[0] == 'read' && scope[1] == 'write') { @@ -403,7 +438,7 @@ describe('exchange.clientCredentials', function() { } return done(new Error('something is wrong')); } - + describe('issuing an access token based on scope separated by space', function() { var response, err; @@ -419,18 +454,18 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('issuing an access token based on scope separated by comma', function() { var response, err; @@ -446,19 +481,19 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); }); - + describe('with user property option issuing an access token', function() { var response, err; @@ -474,16 +509,16 @@ describe('exchange.clientCredentials', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + }); diff --git a/test/exchange/password.test.js b/test/exchange/password.test.js index d3d2aba5..3afde8de 100644 --- a/test/exchange/password.test.js +++ b/test/exchange/password.test.js @@ -3,7 +3,7 @@ var chai = require('chai') describe('exchange.password', function() { - + function issue(client, username, passwd, done) { if (client.id == 'c123' && username == 'bob' && passwd == 'shh') { return done(null, 's3cr1t') @@ -22,17 +22,17 @@ describe('exchange.password', function() { } return done(new Error('something is wrong')); } - + it('should be named password', function() { expect(password(function(){}).name).to.equal('password'); }); - + it('should throw if constructed without a issue callback', function() { expect(function() { password(); }).to.throw(TypeError, 'oauth2orize.password exchange requires an issue callback'); }); - + describe('issuing an access token', function() { var response, err; @@ -48,18 +48,18 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('issuing an access token and refresh token', function() { var response, err; @@ -75,18 +75,18 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","refresh_token":"getANotehr","token_type":"Bearer"}'); }); }); - + describe('issuing an access token and params', function() { var response, err; @@ -102,18 +102,18 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","expires_in":3600,"token_type":"Bearer"}'); }); }); - + describe('issuing an access token, null refresh token, and params', function() { var response, err; @@ -129,18 +129,18 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","expires_in":3600,"token_type":"Bearer"}'); }); }); - + describe('issuing an access token, refresh token, and params with token_type', function() { var response, err; @@ -156,18 +156,18 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","refresh_token":"blahblag","token_type":"foo","expires_in":3600}'); }); }); - + describe('issuing an access token based on scope', function() { function issue(client, username, passwd, scope, done) { if (client.id == 'c123' && username == 'bob' && passwd == 'shh' @@ -176,7 +176,7 @@ describe('exchange.password', function() { } return done(new Error('something is wrong')); } - + var response, err; before(function(done) { @@ -191,18 +191,18 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('issuing an access token based on scope and body', function() { function issue(client, username, passwd, scope, body, done) { if (client.id == 'c123' && username == 'bob' && passwd == 'shh' @@ -212,7 +212,43 @@ describe('exchange.password', function() { } return done(new Error('something is wrong')); } - + + var response, err; + + before(function(done) { + chai.connect.use(password(issue)) + .req(function(req) { + req.user = { id: 'c123', name: 'Example' }; + req.body = { username: 'bob', password: 'shh', scope: 'read', audience: 'https://www.example.com/' }; + }) + .end(function(res) { + response = res; + done(); + }) + .dispatch(); + }); + + it('should respond with headers', function() { + expect(response.getHeader('Content-Type')).to.equal('application/json'); + expect(response.getHeader('Cache-Control')).to.equal('no-store'); + expect(response.getHeader('Pragma')).to.equal('no-cache'); + }); + + it('should respond with body', function() { + expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); + }); + }); + + describe('issuing an access token based on scope and body with access to headers', function() { + function issue(client, username, passwd, scope, body, headers, done) { + if (client.id == 'c123' && username == 'bob' && passwd == 'shh' + && scope.length == 1 && scope[0] == 'read' + && body.audience == 'https://www.example.com/' && headers != null) { + return done(null, 's3cr1t') + } + return done(new Error('something is wrong')); + } + var response, err; before(function(done) { @@ -227,18 +263,18 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('issuing an access token based on array of scopes', function() { function issue(client, username, passwd, scope, done) { if (client.id == 'c123' && username == 'bob' && passwd == 'shh' @@ -247,7 +283,7 @@ describe('exchange.password', function() { } return done(new Error('something is wrong')); } - + var response, err; before(function(done) { @@ -262,18 +298,18 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('not issuing an access token', function() { var response, err; @@ -289,7 +325,7 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.constructor.name).to.equal('TokenError'); @@ -298,7 +334,7 @@ describe('exchange.password', function() { expect(err.status).to.equal(403); }); }); - + describe('handling a request without username parameter', function() { var response, err; @@ -314,7 +350,7 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.constructor.name).to.equal('TokenError'); @@ -323,7 +359,7 @@ describe('exchange.password', function() { expect(err.status).to.equal(400); }); }); - + describe('handling a request without password parameter', function() { var response, err; @@ -339,7 +375,7 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.constructor.name).to.equal('TokenError'); @@ -348,7 +384,7 @@ describe('exchange.password', function() { expect(err.status).to.equal(400); }); }); - + describe('encountering an error while issuing an access token', function() { var response, err; @@ -364,13 +400,13 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.message).to.equal('something is wrong'); }); }); - + describe('encountering an exception while issuing an access token', function() { var response, err; @@ -386,13 +422,13 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.message).to.equal('something was thrown'); }); }); - + describe('handling a request without a body', function() { var response, err; @@ -407,13 +443,13 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.message).to.equal('OAuth2orize requires body parsing. Did you forget app.use(express.bodyParser())?'); }); }); - + describe('with scope separator option', function() { describe('issuing an access token based on array of scopes', function() { function issue(client, username, passwd, scope, done) { @@ -423,7 +459,7 @@ describe('exchange.password', function() { } return done(new Error('something is wrong')); } - + var response, err; before(function(done) { @@ -438,19 +474,19 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); }); - + describe('with multiple scope separator option', function() { function issue(client, username, passwd, scope, done) { if (client.id == 'c123' && username == 'bob' && passwd == 'shh' @@ -459,7 +495,7 @@ describe('exchange.password', function() { } return done(new Error('something is wrong')); } - + describe('issuing an access token based on scope separated by space', function() { var response, err; @@ -475,18 +511,18 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('issuing an access token based on scope separated by comma', function() { var response, err; @@ -502,19 +538,19 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); }); - + describe('with user property option issuing an access token', function() { var response, err; @@ -530,16 +566,16 @@ describe('exchange.password', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + }); diff --git a/test/exchange/refreshToken.test.js b/test/exchange/refreshToken.test.js index 382bf992..cce79bdb 100644 --- a/test/exchange/refreshToken.test.js +++ b/test/exchange/refreshToken.test.js @@ -3,7 +3,7 @@ var chai = require('chai') describe('exchange.refreshToken', function() { - + function issue(client, refreshToken, done) { if (client.id == 'c123' && refreshToken == 'refreshing') { return done(null, 's3cr1t') @@ -22,17 +22,17 @@ describe('exchange.refreshToken', function() { } return done(new Error('something is wrong')); } - + it('should be named refresh_token', function() { expect(refreshToken(function(){}).name).to.equal('refresh_token'); }); - + it('should throw if constructed without a issue callback', function() { expect(function() { refreshToken(); }).to.throw(TypeError, 'oauth2orize.refreshToken exchange requires an issue callback'); }); - + describe('issuing an access token', function() { var response, err; @@ -48,18 +48,18 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('issuing an access token and refresh token', function() { var response, err; @@ -75,18 +75,18 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","refresh_token":"getANotehr","token_type":"Bearer"}'); }); }); - + describe('issuing an access token and params', function() { var response, err; @@ -102,18 +102,18 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","expires_in":3600,"token_type":"Bearer"}'); }); }); - + describe('issuing an access token, null refresh token, and params', function() { var response, err; @@ -129,18 +129,18 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","expires_in":3600,"token_type":"Bearer"}'); }); }); - + describe('issuing an access token, refresh token, and params with token_type', function() { var response, err; @@ -156,18 +156,18 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","refresh_token":"blahblag","token_type":"foo","expires_in":3600}'); }); }); - + describe('issuing an access token based on scope', function() { function issue(client, refreshToken, scope, done) { if (client.id == 'c123' && refreshToken == 'refreshing' @@ -176,7 +176,7 @@ describe('exchange.refreshToken', function() { } return done(new Error('something is wrong')); } - + var response, err; before(function(done) { @@ -191,18 +191,90 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + + describe('issuing an access token based on scope and body', function() { + function issue(client, refreshToken, scope, body, done) { + if (client.id == 'c123' && refreshToken == 'refreshing' + && scope.length == 1 && scope[0] == 'read' + && body.audience == 'https://www.example.com/') { + return done(null, 's3cr1t') + } + return done(new Error('something is wrong')); + } + + var response, err; + + before(function(done) { + chai.connect.use(refreshToken(issue)) + .req(function(req) { + req.user = { id: 'c123', name: 'Example' }; + req.body = { refresh_token: 'refreshing', scope: 'read', audience: 'https://www.example.com/' }; + }) + .end(function(res) { + response = res; + done(); + }) + .dispatch(); + }); + + it('should respond with headers', function() { + expect(response.getHeader('Content-Type')).to.equal('application/json'); + expect(response.getHeader('Cache-Control')).to.equal('no-store'); + expect(response.getHeader('Pragma')).to.equal('no-cache'); + }); + + it('should respond with body', function() { + expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); + }); + }); + + describe('issuing an access token based on scope and body with access to headers', function() { + function issue(client, refreshToken, scope, body, headers, done) { + if (client.id == 'c123' && refreshToken == 'refreshing' + && scope.length == 1 && scope[0] == 'read' + && body.audience == 'https://www.example.com/' && headers != null) { + return done(null, 's3cr1t') + } + return done(new Error('something is wrong')); + } + + var response, err; + + before(function(done) { + chai.connect.use(refreshToken(issue)) + .req(function(req) { + req.user = { id: 'c123', name: 'Example' }; + req.body = { refresh_token: 'refreshing', scope: 'read', audience: 'https://www.example.com/' }; + }) + .end(function(res) { + response = res; + done(); + }) + .dispatch(); + }); + + it('should respond with headers', function() { + expect(response.getHeader('Content-Type')).to.equal('application/json'); + expect(response.getHeader('Cache-Control')).to.equal('no-store'); + expect(response.getHeader('Pragma')).to.equal('no-cache'); + }); + + it('should respond with body', function() { + expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); + }); + }); + describe('issuing an access token based on array of scopes', function() { function issue(client, refreshToken, scope, done) { if (client.id == 'c123' && refreshToken == 'refreshing' @@ -211,7 +283,7 @@ describe('exchange.refreshToken', function() { } return done(new Error('something is wrong')); } - + var response, err; before(function(done) { @@ -226,18 +298,18 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('not issuing an access token', function() { var response, err; @@ -253,7 +325,7 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.constructor.name).to.equal('TokenError'); @@ -262,7 +334,7 @@ describe('exchange.refreshToken', function() { expect(err.status).to.equal(403); }); }); - + describe('handling a request without refresh token parameter', function() { var response, err; @@ -278,7 +350,7 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.constructor.name).to.equal('TokenError'); @@ -287,7 +359,7 @@ describe('exchange.refreshToken', function() { expect(err.status).to.equal(400); }); }); - + describe('encountering an error while issuing an access token', function() { var response, err; @@ -303,13 +375,13 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.message).to.equal('something is wrong'); }); }); - + describe('encountering an exception while issuing an access token', function() { var response, err; @@ -325,13 +397,13 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.message).to.equal('something was thrown'); }); }); - + describe('handling a request without a body', function() { var response, err; @@ -346,13 +418,13 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should error', function() { expect(err).to.be.an.instanceOf(Error); expect(err.message).to.equal('OAuth2orize requires body parsing. Did you forget app.use(express.bodyParser())?'); }); }); - + describe('with scope separator option', function() { describe('issuing an access token based on array of scopes', function() { function issue(client, refreshToken, scope, done) { @@ -362,7 +434,7 @@ describe('exchange.refreshToken', function() { } return done(new Error('something is wrong')); } - + var response, err; before(function(done) { @@ -377,19 +449,19 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); }); - + describe('with multiple scope separator option', function() { function issue(client, refreshToken, scope, done) { if (client.id == 'c123' && refreshToken == 'refreshing' @@ -398,7 +470,7 @@ describe('exchange.refreshToken', function() { } return done(new Error('something is wrong')); } - + describe('issuing an access token based on scope separated by space', function() { var response, err; @@ -414,18 +486,18 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + describe('issuing an access token based on scope separated by comma', function() { var response, err; @@ -441,19 +513,19 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); }); - + describe('with user property option issuing an access token', function() { var response, err; @@ -469,16 +541,16 @@ describe('exchange.refreshToken', function() { }) .dispatch(); }); - + it('should respond with headers', function() { expect(response.getHeader('Content-Type')).to.equal('application/json'); expect(response.getHeader('Cache-Control')).to.equal('no-store'); expect(response.getHeader('Pragma')).to.equal('no-cache'); }); - + it('should respond with body', function() { expect(response.body).to.equal('{"access_token":"s3cr1t","token_type":"Bearer"}'); }); }); - + });