diff --git a/packages/core/src/authenticatedFetch/dpopUtils.spec.ts b/packages/core/src/authenticatedFetch/dpopUtils.spec.ts index 700015f772..529bc2fea0 100644 --- a/packages/core/src/authenticatedFetch/dpopUtils.spec.ts +++ b/packages/core/src/authenticatedFetch/dpopUtils.spec.ts @@ -66,6 +66,19 @@ describe("createDpopHeader", () => { expect(payload.htu).toBe("https://some.resource/"); }); + it("creates a JWT with 'htu' that needs to be normalized", async () => { + const header = await createDpopHeader( + "https://user:pass@some.resource/?query#hash", + "GET", + await mockKeyPair() + ); + const { payload } = await jwtVerify(header, (await mockJwk()).publicKey); + expect(payload.htm).toBe("GET"); + expect(payload.jti).toBeDefined(); + // The IRI is normalized, hence the trailing '/' + expect(payload.htu).toBe("https://some.resource/"); + }); + it("creates a JWT with the appropriate protected header", async () => { const header = await createDpopHeader( "https://some.resource", diff --git a/packages/core/src/authenticatedFetch/dpopUtils.ts b/packages/core/src/authenticatedFetch/dpopUtils.ts index 4374d9a6fb..b3212ed648 100644 --- a/packages/core/src/authenticatedFetch/dpopUtils.ts +++ b/packages/core/src/authenticatedFetch/dpopUtils.ts @@ -30,11 +30,12 @@ import { PREFERRED_SIGNING_ALG } from "../constant"; * @returns The normalized URL as a string. * @hidden */ -function removeHashUsernameAndPassword(audience: string): string { +function normalizeHTU(audience: string): string { const cleanedAudience = new URL(audience); cleanedAudience.hash = ""; cleanedAudience.username = ""; cleanedAudience.password = ""; + cleanedAudience.search = ""; return cleanedAudience.toString(); } @@ -58,7 +59,7 @@ export async function createDpopHeader( dpopKey: KeyPair ): Promise { return new SignJWT({ - htu: removeHashUsernameAndPassword(audience), + htu: normalizeHTU(audience), htm: method.toUpperCase(), jti: v4(), })