diff --git a/conformance/runner.ts b/conformance/runner.ts index 01400856..7af9b061 100644 --- a/conformance/runner.ts +++ b/conformance/runner.ts @@ -443,9 +443,10 @@ export const flow = (options?: MacroOptions) => { DPoP, }) } - let response: Response + let response = await request() try { - response = await request() + let result = await oauth.processUserInfoResponse(as, client, sub!, response) + t.log('userinfo endpoint response', { ...result }) } catch (err) { t.log('error', inspect(err, { depth: Infinity })) if (DPoP && err instanceof oauth.WWWAuthenticateChallengeError) { @@ -464,9 +465,6 @@ export const flow = (options?: MacroOptions) => { throw err } } - - const result = await oauth.processUserInfoResponse(as, client, sub!, response) - t.log('userinfo endpoint response', { ...result }) } if (accounts_endpoint) { diff --git a/src/index.ts b/src/index.ts index 3045b89c..f9868f94 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2618,23 +2618,7 @@ export interface ProtectedResourceRequestOptions [clockSkew]?: number } -/** - * Performs a protected resource request at an arbitrary URL. - * - * Authorization Header is used to transmit the Access Token value. - * - * @param accessToken The Access Token for the request. - * @param method The HTTP method for the request. - * @param url Target URL for the request. - * @param headers Headers for the request. - * @param body Request body compatible with the Fetch API and the request's method. - * - * @group Accessing Protected Resources - * - * @see [RFC 6750 - The OAuth 2.0 Authorization Framework: Bearer Token Usage](https://www.rfc-editor.org/rfc/rfc6750.html#section-2.1) - * @see [RFC 9449 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.rfc-editor.org/rfc/rfc9449.html#name-protected-resource-access) - */ -export async function protectedResourceRequest( +async function resourceRequest( accessToken: string, method: string, url: URL, @@ -2672,18 +2656,46 @@ export async function protectedResourceRequest( method, redirect: 'manual', signal: options?.signal ? signal(options.signal) : null, + }).then(processDpopNonce) +} + +/** + * Performs a protected resource request at an arbitrary URL. + * + * Authorization Header is used to transmit the Access Token value. + * + * @param accessToken The Access Token for the request. + * @param method The HTTP method for the request. + * @param url Target URL for the request. + * @param headers Headers for the request. + * @param body Request body compatible with the Fetch API and the request's method. + * + * @returns Resolves with a {@link !Response} instance. WWW-Authenticate HTTP Header challenges are + * rejected with {@link WWWAuthenticateChallengeError}. + * + * @group Accessing Protected Resources + * + * @see [RFC 6750 - The OAuth 2.0 Authorization Framework: Bearer Token Usage](https://www.rfc-editor.org/rfc/rfc6750.html#section-2.1) + * @see [RFC 9449 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.rfc-editor.org/rfc/rfc9449.html#name-protected-resource-access) + */ +export async function protectedResourceRequest( + accessToken: string, + method: string, + url: URL, + headers?: Headers, + body?: ProtectedResourceRequestBody, + options?: ProtectedResourceRequestOptions, +): Promise { + return resourceRequest(accessToken, method, url, headers, body, options).then((response) => { + let challenges: WWWAuthenticateChallenge[] | undefined + if ((challenges = parseWwwAuthenticateChallenges(response))) { + throw new WWWAuthenticateChallengeError( + 'server responded with a challenge in the WWW-Authenticate HTTP Header', + { cause: challenges, response }, + ) + } + return response }) - .then(processDpopNonce) - .then((response) => { - let challenges: WWWAuthenticateChallenge[] | undefined - if ((challenges = parseWwwAuthenticateChallenges(response))) { - throw new WWWAuthenticateChallengeError( - 'server responded with a challenge in the WWW-Authenticate HTTP Header', - { cause: challenges, response }, - ) - } - return response - }) } export interface UserInfoRequestOptions extends HttpRequestOptions<'GET'>, DPoPRequestOptions {} @@ -2728,7 +2740,7 @@ export async function userInfoRequest( headers.append('accept', 'application/jwt') } - return protectedResourceRequest(accessToken, 'GET', url, headers, null, { + return resourceRequest(accessToken, 'GET', url, headers, null, { ...options, [clockSkew]: getClockSkew(client), } as ProtectedResourceRequestOptions)