Skip to content

Commit

Permalink
Allow providerParams to be a method invoked with the request
Browse files Browse the repository at this point in the history
  • Loading branch information
connor4312 committed Jun 15, 2016
1 parent b38c3f7 commit 165ea4a
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 5 deletions.
3 changes: 1 addition & 2 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@ Each strategy accepts the following optional settings:
- `isHttpOnly` - sets the cookie HTTP only flag. Defaults to `true`.
- `ttl` - cookie time-to-live in milliseconds. Defaults to `null` (session time-life - cookies are deleted when the browser is closed).
- `domain` - the domain scope. Defaults to `null` (no domain).
- `providerParams` - provider-specific query parameters for the authentication endpoint. Each provider supports its own set of parameters
which customize the user's login experience. For example:
- `providerParams` - provider-specific query parameters for the authentication endpoint. It may be passed either as an object to merge into the query string, or a function which takes the client's `request` and returns an object. Each provider supports its own set of parameters which customize the user's login experience. For example:
- Facebook supports `display` ('page', 'popup', or 'touch'), `auth_type`, `auth_nonce`.
- Google supports `access_type`, `approval_prompt`, `prompt`, `login_hint`, `user_id`, `hd`.
- Twitter supports `force_login`, `screen_name`.
Expand Down
2 changes: 1 addition & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ internals.schema = Joi.object({
isHttpOnly: Joi.boolean(),
ttl: Joi.number(),
domain: Joi.string().allow(null),
providerParams: Joi.object(),
providerParams: Joi.alternatives().try(Joi.object(), Joi.func()),
allowRuntimeProviderParams: Joi.boolean().default(false),
scope: Joi.array().items(Joi.string()).when('provider.protocol', { is: 'oauth2', otherwise: Joi.forbidden() }),
name: Joi.string().required(),
Expand Down
10 changes: 8 additions & 2 deletions lib/oauth.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ exports.v1 = function (settings) {

reply.state(cookie, state);

const authQuery = settings.providerParams ? Hoek.clone(settings.providerParams) : {};
const authQuery = internals.resolveProviderParams(request, settings.providerParams);
authQuery.oauth_token = payload.oauth_token;

if (settings.allowRuntimeProviderParams ) {
Expand Down Expand Up @@ -162,7 +162,7 @@ exports.v2 = function (settings) {

if (!request.query.code) {
const nonce = Cryptiles.randomString(internals.nonceLength);
query = Hoek.clone(settings.providerParams) || {};
query = internals.resolveProviderParams(request, settings.providerParams);

if (settings.allowRuntimeProviderParams ) {
Hoek.merge(query, request.query);
Expand Down Expand Up @@ -624,3 +624,9 @@ internals.getProtocol = (request, settings) => {
settings.location.indexOf('https:') !== -1
) ? 'https' : request.connection.info.protocol;
};

internals.resolveProviderParams = (request, params) => {

const obj = typeof params === 'function' ? params(request) : params;
return obj ? Hoek.clone(obj) : {};
};
45 changes: 45 additions & 0 deletions test/oauth.js
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,51 @@ describe('Bell', () => {
});
});

it('authenticates an endpoint via oauth with a function as provider parameters', (done) => {

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

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

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

server.auth.strategy('custom', 'bell', {
password: 'cookie_encryption_password_secure',
isSecure: false,
clientId: 'test',
clientSecret: 'secret',
provider: provider,
providerParams: (request) => ({ value: request.query.foo })
});

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

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

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

expect(res.headers.location).to.equal(mock.uri + '/auth?value=bar&oauth_token=1');
mock.server.inject(res.headers.location, (response) => {

expect(response.headers.location).to.equal('http://localhost:80/login?oauth_token=1&oauth_verifier=123&extra=true');
mock.stop(done);
});
});
});
});
});

it('passes profileParams', { parallel: false }, (done) => {

const mock = new Mock.V1();
Expand Down

0 comments on commit 165ea4a

Please sign in to comment.