Skip to content

Commit

Permalink
Ensure only 1 authentication method is used during /token access in o…
Browse files Browse the repository at this point in the history
…auth2
  • Loading branch information
ldesplat committed Jun 5, 2015
1 parent ab59ba4 commit 96ef98c
Show file tree
Hide file tree
Showing 17 changed files with 85 additions and 6 deletions.
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ internals.schema = Joi.object({
protocol: Joi.string().valid('oauth', 'oauth2'),
temporary: Joi.string().when('protocol', { is: 'oauth', then: Joi.required(), otherwise: Joi.forbidden() }),
auth: Joi.string().required(),
authMethod: Joi.string().valid('basic', 'param').when('protocol', { is: 'oauth2', then: Joi.required(), otherwize: Joi.forbidden() }),
token: Joi.string().required(),
headers: Joi.object(),
profile: Joi.func(),
Expand Down
14 changes: 10 additions & 4 deletions lib/oauth.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,21 +189,27 @@ exports.v2 = function (settings) {
}

query = {
client_id: settings.clientId,
client_secret: settings.clientSecret,
grant_type: 'authorization_code',
code: request.query.code,
redirect_uri: internals.location(request, protocol, settings.location)
};

if (settings.provider.authMethod === 'param') {
query.client_id = settings.clientId;
query.client_secret = settings.client_secret;
}

var requestOptions = {
payload: internals.queryString(query),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + (new Buffer(settings.clientId + ':' + settings.clientSecret, 'utf8')).toString('base64')
'Content-Type': 'application/x-www-form-urlencoded'
}
};

if (settings.provider.authMethod === 'basic') {
requestOptions.headers.Authorization = 'Basic ' + (new Buffer(settings.clientId + ':' + settings.clientSecret, 'utf8')).toString('base64');
}

if (settings.provider.headers) {
Hoek.merge(requestOptions.headers, settings.provider.headers);
}
Expand Down
1 change: 1 addition & 0 deletions lib/providers/arcgisonline.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'param',
auth: 'https://www.arcgis.com/sharing/rest/oauth2/authorize',
token: 'https://www.arcgis.com/sharing/rest/oauth2/token',
scope: [],
Expand Down
1 change: 1 addition & 0 deletions lib/providers/dropbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'param',
auth: 'https://www.dropbox.com/1/oauth2/authorize',
token: 'https://api.dropbox.com/1/oauth2/token',
profile: function (credentials, params, get, callback) {
Expand Down
1 change: 1 addition & 0 deletions lib/providers/facebook.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'param',
auth: 'https://www.facebook.com/v2.3/dialog/oauth',
token: 'https://graph.facebook.com/oauth/access_token',
scope: ['email'],
Expand Down
1 change: 1 addition & 0 deletions lib/providers/foursquare.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'param',
auth: 'https://foursquare.com/oauth2/authenticate',
token: 'https://foursquare.com/oauth2/access_token',
profile: function (credentials, params, get, callback) {
Expand Down
1 change: 1 addition & 0 deletions lib/providers/github.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'param',
auth: uri + '/login/oauth/authorize',
token: uri + '/login/oauth/access_token',
scope: ['user:email'],
Expand Down
1 change: 1 addition & 0 deletions lib/providers/google.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'param',
auth: 'https://accounts.google.com/o/oauth2/auth',
token: 'https://accounts.google.com/o/oauth2/token',
scope: ['openid', 'email'],
Expand Down
1 change: 1 addition & 0 deletions lib/providers/instagram.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'param',
auth: 'https://api.instagram.com/oauth/authorize',
token: 'https://api.instagram.com/oauth/access_token',
scope: ['basic'],
Expand Down
1 change: 1 addition & 0 deletions lib/providers/linkedin.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'param',
auth: 'https://www.linkedin.com/uas/oauth2/authorization',
token: 'https://www.linkedin.com/uas/oauth2/accessToken',
scope: ['r_fullprofile', 'r_emailaddress', 'r_contactinfo'],
Expand Down
1 change: 1 addition & 0 deletions lib/providers/live.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'param',
auth: 'https://login.live.com/oauth20_authorize.srf',
token: 'https://login.live.com/oauth20_token.srf',
scope: ['wl.basic', 'wl.emails'],
Expand Down
1 change: 1 addition & 0 deletions lib/providers/nest.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'param',
auth: 'https://home.nest.com/login/oauth2',
token: 'https://api.home.nest.com/oauth2/access_token'
};
Expand Down
1 change: 1 addition & 0 deletions lib/providers/phabricator.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'param',
auth: settings.uri + '/oauthserver/auth/',
token: settings.uri + '/oauthserver/token/',
scope: ['whoami'],
Expand Down
1 change: 1 addition & 0 deletions lib/providers/reddit.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'basic',
auth: 'https://www.reddit.com/api/v1/authorize',
token: 'https://www.reddit.com/api/v1/access_token',
scope: ['identity'], // minimal scope to request
Expand Down
1 change: 1 addition & 0 deletions lib/providers/vk.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exports = module.exports = function (options) {

return {
protocol: 'oauth2',
authMethod: 'param',
auth: 'https://oauth.vk.com/authorize',
token: 'https://oauth.vk.com/access_token',
profile: function (credentials, params, get, callback) {
Expand Down
51 changes: 51 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,57 @@ describe('Bell', function () {
});
});

it('authenticates an endpoint via oauth2 and basic authentication', function (done) {

var mock = new Mock.V2('basic');
mock.start(function (provider) {

var server = new Hapi.Server();
server.connection({ host: 'localhost', port: 80 });
server.register(Bell, function (err) {

expect(err).to.not.exist();

server.auth.strategy('custom', 'bell', {
password: 'password',
isSecure: false,
clientId: 'test',
clientSecret: 'secret',
provider: provider
});

server.route({
method: '*',
path: '/login',
config: {
auth: 'custom',
handler: function (request, reply) {

reply(request.auth.credentials);
}
}
});

server.inject('/login', function (res) {

var cookie = res.headers['set-cookie'][0].split(';')[0] + ';';
expect(res.headers.location).to.contain(mock.uri + '/auth?client_id=test&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A80%2Flogin&state=');

mock.server.inject(res.headers.location, function (res) {

expect(res.headers.location).to.contain('http://localhost:80/login?code=1&state=');

server.inject({ url: res.headers.location, headers: { cookie: cookie } }, function (res) {

expect(res.result.provider).to.equal('custom');
mock.stop(done);
});
});
});
});
});
});

it('overrides cookie name', function (done) {

var mock = new Mock.V1();
Expand Down
12 changes: 10 additions & 2 deletions test/mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,10 @@ internals.V1.prototype.stop = function (callback) {
};


exports.V2 = internals.V2 = function () {
exports.V2 = internals.V2 = function (authMethod) {

this.codes = {};
this.authMethod = authMethod ? authMethod : 'param';

this.server = new Hapi.Server();
this.server.connection({ host: 'localhost' });
Expand Down Expand Up @@ -188,7 +189,13 @@ exports.V2 = internals.V2 = function () {
var code = this.codes[request.payload.code];
expect(code).to.exist();
expect(code.redirect_uri).to.equal(request.payload.redirect_uri);
expect(code.client_id).to.equal(request.payload.client_id);
if (authMethod === 'param') {
expect(code.client_id).to.equal(request.payload.client_id);
}
else if (authMethod === 'basic') {
var basic = new Buffer(request.headers.authorization.slice(6), 'base64').toString();
expect(basic).to.startWith(code.client_id);
}

var payload = {
access_token: '456',
Expand Down Expand Up @@ -229,6 +236,7 @@ internals.V2.prototype.start = function (callback) {

return callback({
protocol: 'oauth2',
authMethod: self.authMethod,
auth: self.server.info.uri + '/auth',
token: self.server.info.uri + '/token'
});
Expand Down

0 comments on commit 96ef98c

Please sign in to comment.