From 4d49f3410c44707099305df9d04e1913f35ff4b1 Mon Sep 17 00:00:00 2001 From: otobongfp Date: Mon, 23 Sep 2024 21:47:30 +0100 Subject: [PATCH 1/7] Update: Custom header to preserve signed url and extract same when verifying --- .DS_Store | Bin 0 -> 6148 bytes src/build.ts | 6 ++++-- src/sign.ts | 8 ++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d10734aee7d7fa43223e98d1dd0334e87155fd20 GIT binary patch literal 6148 zcmeHK!A=4(5PbuC0L27vUQG4}B=HXxgae6skPlE{l_&^C;J$bN!C&zEJn5UZA#8=j zlQCu{>AY?`Z`ygAY_|ZUv&v6_CV(27Vx>;E#dKcVH>-pZ<%#C#Pv@iIbUx&>CN%r| z3h28_kYkP!7Sa1_bFTI2%oVbSbM$eB9xgGUZ{Z1fnIp#$r-2!B=eWZ)qqVofluyxG z@*43D@r+yUX+l3{{0UjQ#|c+`#De`Q^ zZQrALQ@|831=b4a_aS9d%mNl3-KT@jT>*#*hn=zSe*KB54iK||g-4Fi#8Zi$D&dMD z;pQNo&iO3F7alzw;#Ov!u(E_3iiC@Yq%Itic{Fbdm;z-5s{XO5=YMba{l84ICsV)_ z_*V)@(j9a=EGe9=--^?-Hf6hEQ`5M@}r-#M> literal 0 HcmV?d00001 diff --git a/src/build.ts b/src/build.ts index 4cc3f2a..255c7a7 100644 --- a/src/build.ts +++ b/src/build.ts @@ -13,8 +13,10 @@ export function extractHeader({ headers }: RequestLike | ResponseLike, header: s } function getUrl(message: RequestLike | ResponseLike, component: string): URL { - if (!(message as RequestLike).url) throw new Error(`${component} is only valid for requests`); - return new URL((message as RequestLike).url); + const urlHeader = extractHeader(message, 'X-Request-URL'); + const urlString = urlHeader || (message as RequestLike).url; + if (!urlString) throw new Error(`${component} is only valid for requests`); + return new URL(urlString); } // see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-message-signatures-06#section-2.3 diff --git a/src/sign.ts b/src/sign.ts index fbb45d5..385251c 100644 --- a/src/sign.ts +++ b/src/sign.ts @@ -47,5 +47,13 @@ export async function sign(message: T, opt message.headers['Signature-Input'] = `${key}=${signatureInputString}`; } + if ('url' in message && message.url) { + if (typeof message.headers.set === 'function') { + message.headers.set('X-Request-URL', message.url); + } else { + message.headers['X-Request-URL'] = message.url; + } + } + return message; } From 36100ed8483a1ee5c63dc0ddc93dce0add164718 Mon Sep 17 00:00:00 2001 From: otobongfp Date: Tue, 24 Sep 2024 11:03:42 +0100 Subject: [PATCH 2/7] Updates: build correct url from request --- src/build.ts | 13 ++++++++----- src/sign.ts | 8 -------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/build.ts b/src/build.ts index 255c7a7..cbef8b8 100644 --- a/src/build.ts +++ b/src/build.ts @@ -12,11 +12,14 @@ export function extractHeader({ headers }: RequestLike | ResponseLike, header: s return val.toString().replace(/\s+/g, ' '); } -function getUrl(message: RequestLike | ResponseLike, component: string): URL { - const urlHeader = extractHeader(message, 'X-Request-URL'); - const urlString = urlHeader || (message as RequestLike).url; - if (!urlString) throw new Error(`${component} is only valid for requests`); - return new URL(urlString); +export function getUrl(message: RequestLike | ResponseLike, component: string): URL { + if ('url' in message && 'protocol' in message) { + const host = extractHeader(message, 'host'); + const baseUrl = `${message.protocol}://${host}`; + return new URL(message.url, baseUrl); + } + if (!(message as RequestLike).url) throw new Error(`${component} is only valid for requests`); + return new URL((message as RequestLike).url); } // see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-message-signatures-06#section-2.3 diff --git a/src/sign.ts b/src/sign.ts index 385251c..fbb45d5 100644 --- a/src/sign.ts +++ b/src/sign.ts @@ -47,13 +47,5 @@ export async function sign(message: T, opt message.headers['Signature-Input'] = `${key}=${signatureInputString}`; } - if ('url' in message && message.url) { - if (typeof message.headers.set === 'function') { - message.headers.set('X-Request-URL', message.url); - } else { - message.headers['X-Request-URL'] = message.url; - } - } - return message; } From 2c981275f9c2fab61c9d0a869ede95391b5d48e8 Mon Sep 17 00:00:00 2001 From: otobongfp Date: Tue, 24 Sep 2024 11:21:39 +0100 Subject: [PATCH 3/7] Add .DS_Store to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bf58f85..fa1ca69 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,6 @@ .idea .nyc_output .yarn +.DS_Store yarn.lock package-lock.json From 4702b67776e383e6c04016a65be3491dfd91e6ab Mon Sep 17 00:00:00 2001 From: otobongfp Date: Tue, 24 Sep 2024 13:02:24 +0100 Subject: [PATCH 4/7] Added unit test for getUrl --- src/build.ts | 4 ++-- src/types.ts | 2 ++ test/build.spec.ts | 22 +++++++++++++++++++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/build.ts b/src/build.ts index cbef8b8..3396a9b 100644 --- a/src/build.ts +++ b/src/build.ts @@ -15,14 +15,14 @@ export function extractHeader({ headers }: RequestLike | ResponseLike, header: s export function getUrl(message: RequestLike | ResponseLike, component: string): URL { if ('url' in message && 'protocol' in message) { const host = extractHeader(message, 'host'); - const baseUrl = `${message.protocol}://${host}`; + const protocol = message.protocol || 'http'; + const baseUrl = `${protocol}://${host}`; return new URL(message.url, baseUrl); } if (!(message as RequestLike).url) throw new Error(`${component} is only valid for requests`); return new URL((message as RequestLike).url); } -// see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-message-signatures-06#section-2.3 export function extractComponent(message: RequestLike | ResponseLike, component: string): string { switch (component) { case '@method': diff --git a/src/types.ts b/src/types.ts index d6c9f0a..8fe5c1c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -29,12 +29,14 @@ export type HeaderValue = { toString(): string } | string | string[] | undefined export type RequestLike = { method: string; url: string; + protocol?: string; headers: Headers; }; export type ResponseLike = { status: number; headers: Headers; + protocol?: string; }; // see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-message-signatures-06#section-2.3.1 diff --git a/test/build.spec.ts b/test/build.spec.ts index ea40737..a0154f2 100644 --- a/test/build.spec.ts +++ b/test/build.spec.ts @@ -1,5 +1,5 @@ import { Component, Parameters, RequestLike } from '../src'; -import { buildSignatureInputString, buildSignedData, extractComponent, extractHeader } from '../src/build'; +import { buildSignatureInputString, buildSignedData, extractComponent, extractHeader, getUrl } from '../src/build'; import { expect } from 'chai'; describe('build', () => { @@ -242,4 +242,24 @@ describe('build', () => { ); }); }); + + describe('getUrl', () => { + it('should correctly construct a full URL from a RequestLike object with protocol and host', () => { + const message: RequestLike = { + method: 'GET', + url: '/path', + protocol: 'https', + headers: { + host: 'www.example.com', + }, + }; + const result = getUrl(message, '@target-uri'); + expect(result.toString()).to.equal('https://www.example.com/path'); + }); + + it('should throw an error if the message does not contain a URL', () => { + const message = {} as RequestLike; + expect(() => getUrl(message, '@target-uri')).to.throw('@target-uri is only valid for requests'); + }); + }); }); From eaf968a48c913be07d4da375e47e6946e105b1b4 Mon Sep 17 00:00:00 2001 From: otobongfp Date: Tue, 24 Sep 2024 13:03:20 +0100 Subject: [PATCH 5/7] Added unit test for getUrl --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index d10734aee7d7fa43223e98d1dd0334e87155fd20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK!A=4(5PbuC0L27vUQG4}B=HXxgae6skPlE{l_&^C;J$bN!C&zEJn5UZA#8=j zlQCu{>AY?`Z`ygAY_|ZUv&v6_CV(27Vx>;E#dKcVH>-pZ<%#C#Pv@iIbUx&>CN%r| z3h28_kYkP!7Sa1_bFTI2%oVbSbM$eB9xgGUZ{Z1fnIp#$r-2!B=eWZ)qqVofluyxG z@*43D@r+yUX+l3{{0UjQ#|c+`#De`Q^ zZQrALQ@|831=b4a_aS9d%mNl3-KT@jT>*#*hn=zSe*KB54iK||g-4Fi#8Zi$D&dMD z;pQNo&iO3F7alzw;#Ov!u(E_3iiC@Yq%Itic{Fbdm;z-5s{XO5=YMba{l84ICsV)_ z_*V)@(j9a=EGe9=--^?-Hf6hEQ`5M@}r-#M> From 29625f5b79b6dd5571ab1fa1b58e5fc6984ebf77 Mon Sep 17 00:00:00 2001 From: otobongfp Date: Tue, 24 Sep 2024 13:07:19 +0100 Subject: [PATCH 6/7] Minor update --- src/build.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/build.ts b/src/build.ts index 3396a9b..b39ec1a 100644 --- a/src/build.ts +++ b/src/build.ts @@ -23,6 +23,7 @@ export function getUrl(message: RequestLike | ResponseLike, component: string): return new URL((message as RequestLike).url); } +// see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-message-signatures-06#section-2.3 export function extractComponent(message: RequestLike | ResponseLike, component: string): string { switch (component) { case '@method': From 0a949f1292582daaf3f3ddf92b14bd07dfc5445e Mon Sep 17 00:00:00 2001 From: otobongfp Date: Tue, 24 Sep 2024 13:07:54 +0100 Subject: [PATCH 7/7] Minor update --- src/types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index 8fe5c1c..831ee6c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -36,7 +36,6 @@ export type RequestLike = { export type ResponseLike = { status: number; headers: Headers; - protocol?: string; }; // see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-message-signatures-06#section-2.3.1