Skip to content

Commit 7eb3076

Browse files
committed
feat(passport): easier way to use OAuth 2.0 Resource Indicators without overloads
1 parent d47d267 commit 7eb3076

File tree

1 file changed

+54
-25
lines changed

1 file changed

+54
-25
lines changed

src/passport.ts

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ export type VerifyFunctionWithRequest = (
2323
verified: passport.AuthenticateCallback,
2424
) => void
2525

26+
export interface AuthenticateOptions extends passport.AuthenticateOptions {
27+
/**
28+
* OAuth 2.0 Resource Indicator(s) to use for the request either for the
29+
* authorization request or token endpoint request, depending on whether it's
30+
* part of {@link Strategy.authenticate} options during the initial redirect or
31+
* callback phase.
32+
*/
33+
resource?: string | string[]
34+
}
35+
2636
/**
2737
* Retrieve an openid-client DPoPHandle for a given request.
2838
*/
@@ -62,6 +72,11 @@ interface StrategyOptionsBase {
6272
* request parameter unless specified elsewhere.
6373
*/
6474
scope?: string
75+
/**
76+
* OAuth 2.0 Resource Indicator(s). This will be used as the `resource`
77+
* authorization request parameter unless specified through other means.
78+
*/
79+
resource?: string | string[]
6580
/**
6681
* Whether the strategy will use PAR. Default is `false`.
6782
*/
@@ -91,6 +106,16 @@ export interface StrategyOptionsWithRequest extends StrategyOptionsBase {
91106
passReqToCallback: true
92107
}
93108

109+
function setResource(params: URLSearchParams, resource: string | string[]) {
110+
if (Array.isArray(resource)) {
111+
for (const value of resource) {
112+
params.append('resource', value)
113+
}
114+
} else {
115+
params.set('resource', resource)
116+
}
117+
}
118+
94119
export class Strategy implements passport.Strategy {
95120
/**
96121
* Name of the strategy
@@ -132,6 +157,10 @@ export class Strategy implements passport.Strategy {
132157
* @internal
133158
*/
134159
_scope?: string
160+
/**
161+
* @internal
162+
*/
163+
_resource: StrategyOptionsBase['resource']
135164

136165
constructor(options: StrategyOptions, verify: VerifyFunction)
137166
constructor(
@@ -162,18 +191,16 @@ export class Strategy implements passport.Strategy {
162191
this._verify = verify
163192
this._callbackURL = options.callbackURL
164193
this._passReqToCallback = options.passReqToCallback
194+
this._resource = options.resource
165195
}
166196

167-
// prettier-ignore
168197
/**
169198
* Return extra parameters to be included an authorization request.
170199
*/
171-
authorizationRequestParams<
172-
TOptions extends
173-
passport.AuthenticateOptions = passport.AuthenticateOptions,
174-
>(
200+
authorizationRequestParams<TOptions extends AuthenticateOptions>(
175201
// @ts-ignore
176-
req: express.Request, options: TOptions,
202+
req: express.Request,
203+
options: TOptions,
177204
): URLSearchParams | Record<string, string> | undefined {
178205
let params = new URLSearchParams()
179206

@@ -189,31 +216,35 @@ export class Strategy implements passport.Strategy {
189216
params.set('prompt', options.prompt)
190217
}
191218

219+
if (options?.resource) {
220+
setResource(params, options.resource)
221+
}
222+
192223
return params
193224
}
194225

195-
// prettier-ignore
196226
/**
197227
* Return extra parameters to be included in the authorization code grant
198228
* token endpoint request.
199229
*/
200-
authorizationCodeGrantParameters<
201-
TOptions extends
202-
passport.AuthenticateOptions = passport.AuthenticateOptions,
203-
>(
230+
authorizationCodeGrantParameters<TOptions extends AuthenticateOptions>(
204231
// @ts-ignore
205-
req: express.Request, options: TOptions,
232+
req: express.Request,
233+
options: TOptions,
206234
): URLSearchParams | Record<string, string> | undefined {
207-
return {}
235+
let params = new URLSearchParams()
236+
237+
if (options?.resource) {
238+
setResource(params, options.resource)
239+
}
240+
241+
return params
208242
}
209243

210244
/**
211245
* @internal
212246
*/
213-
async authorizationRequest<
214-
TOptions extends
215-
passport.AuthenticateOptions = passport.AuthenticateOptions,
216-
>(
247+
async authorizationRequest<TOptions extends AuthenticateOptions>(
217248
this: passport.StrategyCreated<
218249
Strategy,
219250
Strategy & passport.StrategyCreatedStatic
@@ -252,6 +283,10 @@ export class Strategy implements passport.Strategy {
252283
redirectTo.searchParams.set('scope', this._scope)
253284
}
254285

286+
if (this._resource && !redirectTo.searchParams.has('resource')) {
287+
setResource(redirectTo.searchParams, this._resource)
288+
}
289+
255290
const DPoP = await this._DPoP?.(req)
256291

257292
if (DPoP && !redirectTo.searchParams.has('dpop_jkt')) {
@@ -312,10 +347,7 @@ export class Strategy implements passport.Strategy {
312347
/**
313348
* @internal
314349
*/
315-
async authorizationCodeGrant<
316-
TOptions extends
317-
passport.AuthenticateOptions = passport.AuthenticateOptions,
318-
>(
350+
async authorizationCodeGrant<TOptions extends AuthenticateOptions>(
319351
this: passport.StrategyCreated<
320352
Strategy,
321353
Strategy & passport.StrategyCreatedStatic
@@ -412,10 +444,7 @@ export class Strategy implements passport.Strategy {
412444
/**
413445
* Authenticate request.
414446
*/
415-
authenticate<
416-
TOptions extends
417-
passport.AuthenticateOptions = passport.AuthenticateOptions,
418-
>(
447+
authenticate<TOptions extends AuthenticateOptions>(
419448
this: passport.StrategyCreated<
420449
Strategy,
421450
Strategy & passport.StrategyCreatedStatic

0 commit comments

Comments
 (0)