Skip to content

Commit

Permalink
Merge pull request #188 from rolodato/master
Browse files Browse the repository at this point in the history
Add Auth0 provider
  • Loading branch information
ldesplat committed Feb 27, 2016
2 parents 203f533 + ffcfb4e commit 7a83ff1
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 1 deletion.
2 changes: 1 addition & 1 deletion API.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ server.register(require('bell'), function (err) {
### Options

The `server.auth.strategy()` method requires the following strategy options:
- `provider` - the name of the third-party provider (`'bitbucket'`, `'dropbox'`, `'facebook'`, `'foursquare'`, `'github'`, `'google'`, `'instagram'`, `'linkedin'`, `'live'`, `'twitter'`, `'vk'`, `'arcgisonline'`, `'yahoo'`, `'nest'`, `'phabricator'`)
- `provider` - the name of the third-party provider (`'auth0'`, `'bitbucket'`, `'dropbox'`, `'facebook'`, `'foursquare'`, `'github'`, `'google'`, `'instagram'`, `'linkedin'`, `'live'`, `'twitter'`, `'vk'`, `'arcgisonline'`, `'yahoo'`, `'nest'`, `'phabricator'`)
or an object containing a custom provider with the following:
- `protocol` - the authorization protocol used. Must be one of:
- `'oauth'` - OAuth 1.0a
Expand Down
35 changes: 35 additions & 0 deletions Providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,41 @@ credentials.profile = {
};
```

### Auth0

[Provider Documentation](https://auth0.com/docs/protocols#oauth-server-side)

- `scope`: not applicable
- `config`:
- `domain`: Your Auth0 domain name, such as `example.auth0.com` or `example.eu.auth0.com`
- `auth`: [/authorize](https://auth0.com/docs/auth-api#!#get--authorize_social)
- `token`: [/oauth/token](https://auth0.com/docs/protocols#3-getting-the-access-token)

To authenticate a user with a specific identity provider directly, use `providerParams`. For example:

```javascript
providerParams: {
connection: 'Username-Password-Authentication'
}
```

The default profile response will look like this:

```javascript
credentials.profile = {
id: profile.user_id,
email: profile.email,
displayName: profile.name,
name: {
first: profile.given_name,
last: profile.family_name
},
raw: profile
};
```

Specific fields may vary depending on the identity provider used. For more information, [refer to the documentation on user profiles](https://auth0.com/docs/user-profile/normalized).

### Bitbucket

[Provider Documentation](https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-238027431.html)
Expand Down
37 changes: 37 additions & 0 deletions lib/providers/auth0.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict';

const Joi = require('joi');
const Hoek = require('hoek');

exports = module.exports = function (options) {

const validated = Joi.validate(options, Joi.object({
domain: Joi.string().hostname().required()
}));
Hoek.assert(!validated.error, validated.error);
const settings = validated.value;
const auth0BaseUrl = `https://${settings.domain}`;
return {
protocol: 'oauth2',
useParamsAuth: true,
auth: `${auth0BaseUrl}/authorize`,
token: `${auth0BaseUrl}/oauth/token`,
profile: function (credentials, params, get, callback) {

get(`${auth0BaseUrl}/userinfo`, null, (profile) => {
// https://auth0.com/docs/user-profile/normalized
credentials.profile = {
id: profile.user_id,
email: profile.email,
displayName: profile.name,
name: {
first: profile.given_name,
last: profile.family_name
},
raw: profile
};
callback();
});
}
};
};
1 change: 1 addition & 0 deletions lib/providers/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

exports = module.exports = {
auth0: require('./auth0'),
bitbucket: require('./bitbucket'),
dropbox: require('./dropbox'),
facebook: require('./facebook'),
Expand Down
121 changes: 121 additions & 0 deletions test/providers/auth0.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
'use strict';

// Load modules

const Bell = require('../../');
const Code = require('code');
const Hapi = require('hapi');
const Hoek = require('hoek');
const Lab = require('lab');
const Mock = require('../mock');


// Test shortcuts

const lab = exports.lab = Lab.script();
const describe = lab.describe;
const it = lab.it;
const expect = Code.expect;


describe('auth0', () => {

it('fails with no domain', { parallel: false }, (done) => {

const mock = new Mock.V2();
mock.start((provider) => {

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

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

expect(Bell.providers.auth0).to.throw(Error);

mock.stop(done);
});
});
});

it('authenticates with mock', { parallel: false }, (done) => {

const mock = new Mock.V2();
mock.start((provider) => {

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

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

const custom = Bell.providers.auth0({ domain: 'example.auth0.com' });
Hoek.merge(custom, provider);

const profile = {
user_id: 'auth0|1234567890',
name: 'steve smith',
given_name: 'steve',
family_name: 'smith',
email: 'steve@example.com'
};

Mock.override('https://example.auth0.com/userinfo', profile);

server.auth.strategy('custom', 'bell', {
config: {
domain: 'example.auth0.com'
},
password: 'cookie_encryption_password_secure',
isSecure: false,
clientId: '123',
clientSecret: 'secret',
provider: custom
});

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

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

server.inject('/login', (res) => {

const cookie = res.headers['set-cookie'][0].split(';')[0] + ';';
mock.server.inject(res.headers.location, (mockRes) => {

server.inject({ url: mockRes.headers.location, headers: { cookie: cookie } }, (response) => {

Mock.clear();
expect(response.result).to.deep.equal({
provider: 'custom',
token: '456',
expiresIn: 3600,
refreshToken: undefined,
query: {},
profile: {
id: 'auth0|1234567890',
displayName: 'steve smith',
name: {
first: 'steve',
last: 'smith'
},
email: 'steve@example.com',
raw: profile
}
});

mock.stop(done);
});
});
});
});
});
});
});

0 comments on commit 7a83ff1

Please sign in to comment.