Skip to content

Commit e9689de

Browse files
committed
docs: note a workaround for redirect_uri with query string or bare origin
Refs: #868 Signed-off-by: Filip Skokan <panva.ip@gmail.com>
1 parent a3ffaef commit e9689de

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

docs/variables/customFetch.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,26 @@ config[client.customFetch] = (...args) => {
138138
return undici.fetch(args[0], { ...args[1], dispatcher: mockAgent }) // prettier-ignore
139139
}
140140
```
141+
142+
Correcting the `redirect_uri` token endpoint request parameter when the
143+
registered redirect URI contains query string components or when URL
144+
normalization alters it (e.g. adding a trailing slash to a bare origin).
145+
The module derives `redirect_uri` from the callback URL by stripping all
146+
query parameters but it cannot distinguish the redirect URI's own
147+
parameters from those added by the authorization server response.
148+
149+
```ts
150+
let config!: client.Configuration
151+
let registeredRedirectUri!: string
152+
153+
config[client.customFetch] = (url, options) => {
154+
if (
155+
options.body instanceof URLSearchParams &&
156+
options.body.get('grant_type') === 'authorization_code'
157+
) {
158+
options.body.set('redirect_uri', registeredRedirectUri)
159+
}
160+
161+
return fetch(url, options)
162+
}
163+
```

src/index.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,31 @@ export const skipSubjectCheck: typeof oauth.skipSubjectCheck =
644644
* return undici.fetch(args[0], { ...args[1], dispatcher: mockAgent }) // prettier-ignore
645645
* }
646646
* ```
647+
*
648+
* @example
649+
*
650+
* Correcting the `redirect_uri` token endpoint request parameter when the
651+
* registered redirect URI contains query string components or when URL
652+
* normalization alters it (e.g. adding a trailing slash to a bare origin).
653+
* The module derives `redirect_uri` from the callback URL by stripping all
654+
* query parameters but it cannot distinguish the redirect URI's own
655+
* parameters from those added by the authorization server response.
656+
*
657+
* ```ts
658+
* let config!: client.Configuration
659+
* let registeredRedirectUri!: string
660+
*
661+
* config[client.customFetch] = (url, options) => {
662+
* if (
663+
* options.body instanceof URLSearchParams &&
664+
* options.body.get('grant_type') === 'authorization_code'
665+
* ) {
666+
* options.body.set('redirect_uri', registeredRedirectUri)
667+
* }
668+
*
669+
* return fetch(url, options)
670+
* }
671+
* ```
647672
*/
648673
export const customFetch: typeof oauth.customFetch = oauth.customFetch
649674

@@ -3337,8 +3362,13 @@ export async function authorizationCodeGrant(
33373362
)
33383363
}
33393364
}
3340-
// TODO: what if searchParams *are* part of the registered redirect_uri?
3341-
// TODO: what if the registered redirect_uri has no pathname and no trailing /
3365+
// Note: stripParams removes all searchParams and hash from the URL to
3366+
// derive redirect_uri for the token endpoint. This won't produce the
3367+
// correct value when the registered redirect_uri itself contains query
3368+
// string components (they'll be stripped too) or when URL normalization
3369+
// alters the URL (e.g. adding a trailing slash to a bare origin). In
3370+
// those cases clients can use customFetch to adjust the redirect_uri
3371+
// sent to the token endpoint.
33423372
redirectUri = stripParams(currentUrl)
33433373
switch (true) {
33443374
case !!jarm:

0 commit comments

Comments
 (0)