diff --git a/API.md b/API.md index 35855cac..2299917e 100755 --- a/API.md +++ b/API.md @@ -226,6 +226,8 @@ The `server.auth.strategy()` method requires the following strategy options: object will be merged with the Wreck request object used to call the token endpoint. Such an object can contain custom HTTP headers or TLS options (e.g. `{ agent: new Https.Agent({ cert: myClientCert, key: myClientKey}) }`). + To allow dynamically updating secret, this option can be passed as a *function* returning string + to be used as `clientSecret`. - `forceHttps` - A boolean indicating whether or not you want the redirect_uri to be forced to https. Useful if your hapi application runs as http, but is accessed through https. - `location` - Set the base redirect_uri manually if it cannot be inferred properly from server diff --git a/lib/index.js b/lib/index.js index 3cc7075a..e440c899 100755 --- a/lib/index.js +++ b/lib/index.js @@ -72,6 +72,7 @@ internals.schema = Joi.object({ clientSecret: Joi.alternatives() .try(Joi.string().allow('')) + .try(Joi.function()) .conditional('provider.protocol', { not: 'oauth', then: Joi.object() diff --git a/lib/oauth.js b/lib/oauth.js index b93e0353..b20475b0 100755 --- a/lib/oauth.js +++ b/lib/oauth.js @@ -263,6 +263,9 @@ exports.v2 = function (settings) { if (typeof settings.clientSecret === 'string') { query.client_secret = settings.clientSecret; } + else if (typeof settings.clientSecret === 'function') { + query.client_secret = settings.clientSecret(); + } } const requestOptions = { diff --git a/test/oauth.js b/test/oauth.js index 7798eb08..12111859 100755 --- a/test/oauth.js +++ b/test/oauth.js @@ -928,6 +928,48 @@ describe('Bell', () => { expect(res.headers.location).to.contain(mock.uri + '/auth?special=true&client_id=test&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Flogin&state='); }); + it('uses clientSecret() function', async (flags) => { + + const mock = await Mock.v2(flags); + const server = Hapi.server({ host: 'localhost', port: 8080 }); + await server.register(Bell); + + let callCount = 0; + const secretGetter = () => { + + callCount += 1; + return 'secret'; + }; + + server.auth.strategy('custom', 'bell', { + password: 'cookie_encryption_password_secure', + isSecure: false, + clientId: 'test', + clientSecret: secretGetter, + provider: mock.provider + }); + + server.route({ + method: '*', + path: '/login', + options: { + auth: 'custom', + handler: function (request, h) { + + return request.auth.credentials; + } + } + }); + + const res1 = await server.inject('/login'); + const cookie = res1.headers['set-cookie'][0].split(';')[0] + ';'; + + const res2 = await mock.server.inject(res1.headers.location); + + await server.inject({ url: res2.headers.location, headers: { cookie } }); + expect(callCount, 'callCount').to.equal(1); + }); + it('forces https in redirect_uri when set in options', async (flags) => { const mock = await Mock.v2(flags);