Skip to content

Commit 6e6cbfe

Browse files
authored
feat: generating callbackUri on fly (#258)
* Support FastifyRequest => string as callbackUri option * Add "callbackUri as function" test
1 parent 9de18d6 commit 6e6cbfe

File tree

5 files changed

+66
-9
lines changed

5 files changed

+66
-9
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ fastify.register(oauthPlugin, {
3434
startRedirectPath: '/login/facebook',
3535
// facebook redirect here after the user login
3636
callbackUri: 'http://localhost:3000/login/facebook/callback'
37+
// You can also define callbackUri as a function that takes a FastifyRequest and returns a string
38+
// callbackUri: req => `${req.protocol}://${req.hostname}/login/facebook/callback`,
3739
})
3840

3941
fastify.get('/login/facebook/callback', async function (request, reply) {

index.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ function fastifyOauth2 (fastify, options, next) {
5050
if (typeof options.credentials !== 'object') {
5151
return next(new Error('options.credentials should be an object'))
5252
}
53-
if (typeof options.callbackUri !== 'string') {
54-
return next(new Error('options.callbackUri should be a string'))
53+
if (typeof options.callbackUri !== 'string' && typeof options.callbackUri !== 'function') {
54+
return next(new Error('options.callbackUri should be a string or a function'))
5555
}
5656
if (options.callbackUriParams && typeof options.callbackUriParams !== 'object') {
5757
return next(new Error('options.callbackUriParams should be a object'))
@@ -168,7 +168,7 @@ function fastifyOauth2 (fastify, options, next) {
168168
}
169169

170170
const urlOptions = Object.assign({}, generateCallbackUriParams(callbackUriParams, request, scope, state), {
171-
redirect_uri: callbackUri,
171+
redirect_uri: typeof callbackUri === 'function' ? callbackUri(request) : callbackUri,
172172
scope,
173173
state
174174
}, pkceParams)
@@ -198,10 +198,10 @@ function fastifyOauth2 (fastify, options, next) {
198198
})
199199
}
200200

201-
const cbk = function (o, code, pkceParams, callback) {
201+
const cbk = function (o, request, code, pkceParams, callback) {
202202
const body = Object.assign({}, tokenRequestParams, {
203203
code,
204-
redirect_uri: callbackUri
204+
redirect_uri: typeof callbackUri === 'function' ? callbackUri(request) : callbackUri
205205
}, pkceParams)
206206

207207
return callbackify(o.oauth2.getToken.bind(o.oauth2, body))(callback)
@@ -241,7 +241,7 @@ function fastifyOauth2 (fastify, options, next) {
241241
callback(err)
242242
return
243243
}
244-
cbk(fastify[name], code, pkceParams, _callback)
244+
cbk(fastify[name], request, code, pkceParams, _callback)
245245
})
246246
}
247247

test/index.test.js

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,51 @@ t.test('fastify-oauth2', t => {
210210
makeRequests(t, fastify)
211211
})
212212

213+
t.test('callbackUri as function', t => {
214+
const fastify = createFastify({ logger: { level: 'silent' } })
215+
216+
fastify.register(fastifyOauth2, {
217+
name: 'githubOAuth2',
218+
credentials: {
219+
client: {
220+
id: 'my-client-id',
221+
secret: 'my-secret'
222+
},
223+
auth: fastifyOauth2.GITHUB_CONFIGURATION
224+
},
225+
startRedirectPath: '/login/github',
226+
callbackUri: req => `${req.protocol}://localhost:3000/callback`,
227+
scope: ['notifications']
228+
})
229+
230+
fastify.get('/', function (request, reply) {
231+
if (this.githubOAuth2 !== this.oauth2GithubOAuth2) {
232+
throw new Error('Expected oauth2GithubOAuth2 to match githubOAuth2')
233+
}
234+
this.githubOAuth2.getAccessTokenFromAuthorizationCodeFlow(request, (err, result) => {
235+
if (err) throw err
236+
237+
// attempts to refresh the token
238+
this.githubOAuth2.getNewAccessTokenUsingRefreshToken(result.token, undefined, (err, result) => {
239+
if (err) throw err
240+
241+
const newToken = result
242+
243+
reply.send({
244+
access_token: newToken.token.access_token,
245+
refresh_token: newToken.token.refresh_token,
246+
expires_in: newToken.token.expires_in,
247+
token_type: newToken.token.token_type
248+
})
249+
})
250+
})
251+
})
252+
253+
t.teardown(fastify.close.bind(fastify))
254+
255+
makeRequests(t, fastify)
256+
})
257+
213258
t.test('promise', t => {
214259
const fastify = createFastify({ logger: { level: 'silent' } })
215260

@@ -1399,7 +1444,7 @@ t.test('options.credentials should be an object', t => {
13991444
})
14001445
})
14011446

1402-
t.test('options.callbackUri should be an object', t => {
1447+
t.test('options.callbackUri should be a string or a function', t => {
14031448
t.plan(1)
14041449

14051450
const fastify = createFastify({ logger: { level: 'silent' } })
@@ -1415,7 +1460,7 @@ t.test('options.callbackUri should be an object', t => {
14151460
}
14161461
})
14171462
.ready(err => {
1418-
t.strictSame(err.message, 'options.callbackUri should be a string')
1463+
t.strictSame(err.message, 'options.callbackUri should be a string or a function')
14191464
})
14201465
})
14211466

types/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ declare namespace fastifyOauth2 {
3434
name: string;
3535
scope?: string[];
3636
credentials: Credentials;
37-
callbackUri: string;
37+
callbackUri: string | ((req: FastifyRequest) => string);
3838
callbackUriParams?: Object;
3939
tokenRequestParams?: Object;
4040
generateStateFunction?: FastifyGenerateStateFunction;

types/index.test-d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,16 @@ expectAssignable<FastifyOAuth2Options>({
7070
pkce: 'S256'
7171
})
7272

73+
expectAssignable<FastifyOAuth2Options>({
74+
name: 'testOAuthName',
75+
scope: scope,
76+
credentials: credentials,
77+
callbackUri: req => `${req.protocol}://${req.hostname}/callback`,
78+
callbackUriParams: {},
79+
startRedirectPath: '/login/testOauth',
80+
pkce: 'S256'
81+
})
82+
7383
expectAssignable<FastifyOAuth2Options>({
7484
name: 'testOAuthName',
7585
scope: scope,

0 commit comments

Comments
 (0)