@fedify/fedify 2.0.8 → 2.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{assert-MZs1qjMx.js → assert-ddO5KLpe.mjs} +5 -9
- package/dist/{assert_equals-DSbWqCm3.js → assert_equals-Ew3jOFa3.mjs} +55 -69
- package/dist/{assert_instance_of-DHz7EHNU.js → assert_instance_of-C4Ri6VuN.mjs} +5 -9
- package/dist/{assert_not_equals-C80BG-_5.js → assert_not_equals--wG9hV7u.mjs} +6 -13
- package/dist/{assert_rejects-Ce45JcFg.js → assert_rejects-B-qJtC9Z.mjs} +6 -11
- package/dist/{assert_throws-BNXdRGWP.js → assert_throws-4NwKEy2q.mjs} +5 -10
- package/dist/{builder-B5cKln9v.js → builder-DDoQaGOu.mjs} +32 -41
- package/dist/{chunk-CGaQZ11T.cjs → chunk-DDcVe30Y.cjs} +23 -24
- package/dist/{chunk-DJNbSFdH.js → chunk-nlSIicah.js} +8 -8
- package/dist/{client-CoCIaTNO.js → client-A1UrnX6I.mjs} +9 -13
- package/dist/{client-BxMZiQaD.d.ts → client-AtlibPOU.d.ts} +1 -1
- package/dist/{client-C97KOq3x.d.cts → client-z-8dc-e1.d.cts} +1 -1
- package/dist/{collection-CcnIw1qY.js → collection-ChgDTHLz.mjs} +7 -12
- package/dist/compat/mod.cjs +5 -8
- package/dist/compat/mod.d.cts +78 -6
- package/dist/compat/mod.d.ts +78 -6
- package/dist/compat/mod.js +4 -8
- package/dist/compat/transformers.test.mjs +62 -0
- package/dist/{context-D3QkEtZd.d.cts → context-CNIt-Qn7.d.cts} +9 -18
- package/dist/{context-DZJhUmzF.d.ts → context-Dyg7P1qW.d.ts} +9 -18
- package/dist/{context-pa9aIrwp.js → context-Juj6bdHC.mjs} +7 -11
- package/dist/deno-CuVDEdyj.mjs +8 -0
- package/dist/{docloader-CBHh0rC5.js → docloader-BPq9yzC_.mjs} +8 -14
- package/dist/{esm-nLm00z9V.js → esm-DVILvP5e.mjs} +50 -89
- package/dist/federation/builder.test.d.mts +2 -0
- package/dist/federation/{builder.test.js → builder.test.mjs} +19 -38
- package/dist/federation/collection.test.d.mts +2 -0
- package/dist/federation/collection.test.mjs +21 -0
- package/dist/federation/handler.test.d.mts +2 -0
- package/dist/federation/{handler.test.js → handler.test.mjs} +26 -56
- package/dist/federation/idempotency.test.d.mts +2 -0
- package/dist/federation/{idempotency.test.js → idempotency.test.mjs} +31 -62
- package/dist/federation/inbox.test.d.mts +2 -0
- package/dist/federation/{inbox.test.js → inbox.test.mjs} +8 -12
- package/dist/federation/keycache.test.d.mts +2 -0
- package/dist/federation/{keycache.test.js → keycache.test.mjs} +11 -15
- package/dist/federation/kv.test.d.mts +2 -0
- package/dist/federation/{kv.test.js → kv.test.mjs} +11 -22
- package/dist/federation/middleware.test.d.mts +2 -0
- package/dist/federation/{middleware.test.js → middleware.test.mjs} +146 -225
- package/dist/federation/mod.cjs +327 -16
- package/dist/federation/mod.d.cts +3 -6
- package/dist/federation/mod.d.ts +3 -6
- package/dist/federation/mod.js +322 -13
- package/dist/federation/mq.test.d.mts +2 -0
- package/dist/federation/{mq.test.js → mq.test.mjs} +21 -35
- package/dist/federation/negotiation.test.d.mts +2 -0
- package/dist/federation/{negotiation.test.js → negotiation.test.mjs} +9 -16
- package/dist/federation/retry.test.d.mts +2 -0
- package/dist/federation/{retry.test.js → retry.test.mjs} +8 -11
- package/dist/federation/router.test.d.mts +2 -0
- package/dist/federation/{router.test.js → router.test.mjs} +11 -16
- package/dist/federation/send.test.d.mts +2 -0
- package/dist/federation/{send.test.js → send.test.mjs} +22 -29
- package/dist/federation/webfinger.test.d.mts +2 -0
- package/dist/federation/{webfinger.test.js → webfinger.test.mjs} +22 -55
- package/dist/{http-DkHdFfrc.d.ts → http-B2wiNmSo.d.ts} +1 -6
- package/dist/{http-C_RwU_oN.js → http-Bz7avX57.js} +25 -156
- package/dist/{http-Cz3MlXAZ.d.cts → http-C_tEAiZj.d.cts} +1 -6
- package/dist/{http-Br3-1dRf.js → http-DI213UHg.mjs} +17 -33
- package/dist/{http-DGs_78tx.cjs → http-DKBDoudA.cjs} +110 -235
- package/dist/{inbox-3bZUqDLE.js → inbox-Bdn-CSRd.mjs} +18 -26
- package/dist/{key-D7Y_J9kt.js → key-DzJf84o7.mjs} +12 -19
- package/dist/{keycache-BASM0rrX.js → keycache-DaQ3ndaJ.mjs} +5 -9
- package/dist/{keys-ZbcByPg9.js → keys-CtZLJq76.mjs} +5 -9
- package/dist/{kv-QzKcOQgP.js → kv-BrZHNugx.mjs} +6 -10
- package/dist/{kv-BL4nlICN.d.cts → kv-CbLNp3zQ.d.cts} +1 -1
- package/dist/{kv-DXEUEP6z.d.ts → kv-GFYnFoOl.d.ts} +1 -1
- package/dist/{kv-cache-CMM5VJsc.js → kv-cache-DBd7BezJ.js} +6 -13
- package/dist/{kv-cache-9PANi4tA.cjs → kv-cache-Dj1Q7TiW.cjs} +27 -34
- package/dist/{kv-cache-El7We5sy.js → kv-cache-OWmRLHir.mjs} +4 -8
- package/dist/{ld-Bjq9Z4St.js → ld-DczS1fLK.mjs} +17 -31
- package/dist/middleware-B5CiOImA.mjs +5 -0
- package/dist/{middleware-Bj30TZll.js → middleware-BKNu57ZI.js} +320 -363
- package/dist/middleware-C36TOX-2.cjs +4 -0
- package/dist/{middleware-CQeA5yF7.cjs → middleware-CyjmpK70.cjs} +513 -564
- package/dist/{middleware-DozhKfB6.js → middleware-DoHz9oIo.mjs} +260 -292
- package/dist/{mod-DPkRU3EK.d.cts → mod-1xhgsHef.d.cts} +2 -2
- package/dist/{mod-DUWcVv49.d.ts → mod-BGtYJZKu.d.ts} +2 -2
- package/dist/{mod-DXsQakeS.d.cts → mod-Bld7oeqf.d.cts} +3 -3
- package/dist/{mod-DnSsduJF.d.ts → mod-BnAKGh2w.d.ts} +2 -2
- package/dist/{mod-CwZXZJ9d.d.ts → mod-DTOUyCce.d.ts} +3 -3
- package/dist/{mod-Di3W5OdP.d.cts → mod-DWoQffTD.d.cts} +2 -2
- package/dist/mod.cjs +29 -68
- package/dist/mod.d.cts +11 -14
- package/dist/mod.d.ts +11 -15
- package/dist/mod.js +17 -65
- package/dist/{negotiation-5NPJL6zp.js → negotiation-BehA2uul.mjs} +7 -11
- package/dist/nodeinfo/client.test.d.mts +2 -0
- package/dist/nodeinfo/{client.test.js → client.test.mjs} +22 -40
- package/dist/nodeinfo/handler.test.d.mts +2 -0
- package/dist/nodeinfo/{handler.test.js → handler.test.mjs} +13 -42
- package/dist/nodeinfo/mod.cjs +5 -8
- package/dist/nodeinfo/mod.d.cts +2 -3
- package/dist/nodeinfo/mod.d.ts +2 -3
- package/dist/nodeinfo/mod.js +4 -8
- package/dist/nodeinfo/types.test.d.mts +2 -0
- package/dist/nodeinfo/{types.test.js → types.test.mjs} +9 -16
- package/dist/otel/exporter.test.d.mts +2 -0
- package/dist/otel/{exporter.test.js → exporter.test.mjs} +117 -169
- package/dist/otel/mod.cjs +15 -20
- package/dist/otel/mod.d.cts +2 -2
- package/dist/otel/mod.d.ts +2 -2
- package/dist/otel/mod.js +8 -14
- package/dist/{owner-gd0Q9FuU.d.ts → owner-74ARJ5TL.d.ts} +1 -1
- package/dist/{owner-1AbPBOOZ.d.cts → owner-CptqhsOy.d.cts} +1 -1
- package/dist/{owner-CImU2dKz.js → owner-DXMGUEOr.mjs} +11 -16
- package/dist/{proof-BygvN4r5.js → proof-C-7NljBU.js} +32 -58
- package/dist/{proof-DLL0MLmV.js → proof-CEOujj0L.mjs} +21 -33
- package/dist/{proof-UhA5do8k.cjs → proof-DMu-6A_w.cjs} +133 -157
- package/dist/{retry-D4GJ670a.js → retry-Ddbq3AcK.mjs} +4 -7
- package/dist/{router-D9eI0s4b.js → router-CrMLXoOr.mjs} +4 -8
- package/dist/runtime/mod.cjs +11 -13
- package/dist/runtime/mod.d.cts +6 -2
- package/dist/runtime/mod.d.ts +0 -1
- package/dist/runtime/mod.js +4 -7
- package/dist/{send-DbW03azY.js → send-DIfrLTB_.mjs} +8 -13
- package/dist/sig/http.test.d.mts +2 -0
- package/dist/sig/{http.test.js → http.test.mjs} +117 -199
- package/dist/sig/key.test.d.mts +2 -0
- package/dist/sig/{key.test.js → key.test.mjs} +11 -18
- package/dist/sig/ld.test.d.mts +2 -0
- package/dist/sig/{ld.test.js → ld.test.mjs} +22 -35
- package/dist/sig/mod.cjs +6 -9
- package/dist/sig/mod.d.cts +3 -3
- package/dist/sig/mod.d.ts +3 -3
- package/dist/sig/mod.js +5 -9
- package/dist/sig/owner.test.d.mts +2 -0
- package/dist/sig/{owner.test.js → owner.test.mjs} +19 -34
- package/dist/sig/proof.test.d.mts +2 -0
- package/dist/sig/{proof.test.js → proof.test.mjs} +16 -27
- package/dist/{std__assert-DWivtrGR.js → std__assert-Duiq_YC9.mjs} +12 -24
- package/dist/testing/{mod.d.ts → mod.d.mts} +26 -78
- package/dist/testing/mod.mjs +6 -0
- package/dist/{transformers-3g8GZwkZ.cjs → transformers-NeAONrAq.cjs} +20 -25
- package/dist/{transformers-C3FLHUd6.js → transformers-ve6e2xcg.js} +3 -7
- package/dist/{types-CPz01LGH.js → types-C37hquWI.mjs} +4 -7
- package/dist/{types-Cd_hszr_.cjs → types-KC4QAoxe.cjs} +29 -34
- package/dist/{types-C93Ob9cU.js → types-hvL8ElAs.js} +8 -13
- package/dist/utils/docloader.test.d.mts +2 -0
- package/dist/utils/{docloader.test.js → docloader.test.mjs} +14 -24
- package/dist/utils/kv-cache.test.d.mts +2 -0
- package/dist/utils/{kv-cache.test.js → kv-cache.test.mjs} +25 -40
- package/dist/utils/mod.cjs +5 -9
- package/dist/utils/mod.d.cts +1 -3
- package/dist/utils/mod.d.ts +1 -3
- package/dist/utils/mod.js +4 -9
- package/dist/vocab/cjs.test.d.mts +2 -0
- package/dist/vocab/cjs.test.mjs +14 -0
- package/dist/vocab/mod.cjs +10 -12
- package/dist/vocab/mod.js +3 -5
- package/package.json +7 -7
- package/dist/compat/transformers.test.d.ts +0 -3
- package/dist/compat/transformers.test.js +0 -87
- package/dist/compat-Bb4NuTUO.js +0 -4
- package/dist/compat-DmDDELst.cjs +0 -4
- package/dist/deno-4w047OFk.js +0 -121
- package/dist/federation/builder.test.d.ts +0 -3
- package/dist/federation/collection.test.d.ts +0 -3
- package/dist/federation/collection.test.js +0 -32
- package/dist/federation/handler.test.d.ts +0 -3
- package/dist/federation/idempotency.test.d.ts +0 -3
- package/dist/federation/inbox.test.d.ts +0 -3
- package/dist/federation/keycache.test.d.ts +0 -3
- package/dist/federation/kv.test.d.ts +0 -3
- package/dist/federation/middleware.test.d.ts +0 -3
- package/dist/federation/mq.test.d.ts +0 -3
- package/dist/federation/negotiation.test.d.ts +0 -3
- package/dist/federation/retry.test.d.ts +0 -3
- package/dist/federation/router.test.d.ts +0 -3
- package/dist/federation/send.test.d.ts +0 -3
- package/dist/federation/webfinger.test.d.ts +0 -3
- package/dist/federation-Bp3HI26G.cjs +0 -350
- package/dist/federation-DaMfqRm4.js +0 -332
- package/dist/middleware-B73ZyDmk.js +0 -12
- package/dist/middleware-Dr61i4Jo.cjs +0 -12
- package/dist/middleware-_1PYruC5.js +0 -26
- package/dist/mod-Bh8mqlYw.d.cts +0 -9
- package/dist/mod-D6HodEq7.d.ts +0 -7
- package/dist/mod-DVwHUI_x.d.cts +0 -80
- package/dist/mod-DosD6NsG.d.ts +0 -82
- package/dist/mod-gq_Xfdz8.d.cts +0 -1
- package/dist/nodeinfo/client.test.d.ts +0 -3
- package/dist/nodeinfo/handler.test.d.ts +0 -3
- package/dist/nodeinfo/types.test.d.ts +0 -3
- package/dist/nodeinfo-DoESQxq5.js +0 -4
- package/dist/nodeinfo-DuMYTpbZ.cjs +0 -4
- package/dist/otel/exporter.test.d.ts +0 -3
- package/dist/runtime-c2Njxsry.cjs +0 -17
- package/dist/runtime-poamPCMb.js +0 -13
- package/dist/sig/http.test.d.ts +0 -3
- package/dist/sig/key.test.d.ts +0 -3
- package/dist/sig/ld.test.d.ts +0 -3
- package/dist/sig/owner.test.d.ts +0 -3
- package/dist/sig/proof.test.d.ts +0 -3
- package/dist/sig-BNhspNOf.js +0 -4
- package/dist/sig-vX39WyWI.cjs +0 -4
- package/dist/testing/mod.js +0 -10
- package/dist/utils/docloader.test.d.ts +0 -3
- package/dist/utils/kv-cache.test.d.ts +0 -3
- package/dist/utils-BQ9KqEK9.cjs +0 -4
- package/dist/utils-Dn5OPdSW.js +0 -4
- /package/dist/{mod-AGjRfPjT.d.ts → compat/transformers.test.d.mts} +0 -0
|
@@ -1,50 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import
|
|
7
|
-
import "../
|
|
8
|
-
import "../
|
|
9
|
-
import { MemoryKvStore } from "../kv-QzKcOQgP.js";
|
|
10
|
-
import "../deno-4w047OFk.js";
|
|
11
|
-
import { createFederation, handleWebFinger } from "../middleware-DozhKfB6.js";
|
|
12
|
-
import "../client-CoCIaTNO.js";
|
|
13
|
-
import "../router-D9eI0s4b.js";
|
|
14
|
-
import "../types-CPz01LGH.js";
|
|
15
|
-
import "../key-D7Y_J9kt.js";
|
|
16
|
-
import "../http-Br3-1dRf.js";
|
|
17
|
-
import "../ld-Bjq9Z4St.js";
|
|
18
|
-
import "../owner-CImU2dKz.js";
|
|
19
|
-
import "../proof-DLL0MLmV.js";
|
|
20
|
-
import "../docloader-CBHh0rC5.js";
|
|
21
|
-
import "../kv-cache-El7We5sy.js";
|
|
22
|
-
import "../inbox-3bZUqDLE.js";
|
|
23
|
-
import "../builder-B5cKln9v.js";
|
|
24
|
-
import "../collection-CcnIw1qY.js";
|
|
25
|
-
import "../keycache-BASM0rrX.js";
|
|
26
|
-
import "../negotiation-5NPJL6zp.js";
|
|
27
|
-
import "../retry-D4GJ670a.js";
|
|
28
|
-
import "../send-DbW03azY.js";
|
|
29
|
-
import "../std__assert-DWivtrGR.js";
|
|
30
|
-
import "../assert_rejects-Ce45JcFg.js";
|
|
31
|
-
import "../assert_throws-BNXdRGWP.js";
|
|
32
|
-
import "../assert_not_equals-C80BG-_5.js";
|
|
33
|
-
import { createRequestContext } from "../context-pa9aIrwp.js";
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
2
|
+
import "urlpattern-polyfill";
|
|
3
|
+
globalThis.addEventListener = () => {};
|
|
4
|
+
import { n as createRequestContext } from "../context-Juj6bdHC.mjs";
|
|
5
|
+
import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
|
|
6
|
+
import "../std__assert-Duiq_YC9.mjs";
|
|
7
|
+
import { t as MemoryKvStore } from "../kv-BrZHNugx.mjs";
|
|
8
|
+
import { a as createFederation, o as handleWebFinger } from "../middleware-DoHz9oIo.mjs";
|
|
34
9
|
import { test } from "@fedify/fixture";
|
|
35
10
|
import { Image, Link, Person } from "@fedify/vocab";
|
|
36
|
-
|
|
37
11
|
//#region src/federation/webfinger.test.ts
|
|
38
12
|
test("handleWebFinger()", async (t) => {
|
|
39
13
|
const url = new URL("https://example.com/.well-known/webfinger");
|
|
40
|
-
function createContext(url
|
|
41
|
-
const federation = createFederation({ kv: new MemoryKvStore() });
|
|
14
|
+
function createContext(url) {
|
|
42
15
|
const context = createRequestContext({
|
|
43
|
-
federation,
|
|
44
|
-
url
|
|
16
|
+
federation: createFederation({ kv: new MemoryKvStore() }),
|
|
17
|
+
url,
|
|
45
18
|
data: void 0,
|
|
46
19
|
getActorUri(identifier) {
|
|
47
|
-
return new URL(`${url
|
|
20
|
+
return new URL(`${url.origin}/users/${identifier}`);
|
|
48
21
|
},
|
|
49
22
|
async getActor(handle) {
|
|
50
23
|
return await actorDispatcher(context, handle);
|
|
@@ -54,10 +27,9 @@ test("handleWebFinger()", async (t) => {
|
|
|
54
27
|
if (uri.protocol === "acct:") return null;
|
|
55
28
|
if (!uri.pathname.startsWith("/users/")) return null;
|
|
56
29
|
const paths = uri.pathname.split("/");
|
|
57
|
-
const identifier = paths[paths.length - 1];
|
|
58
30
|
return {
|
|
59
31
|
type: "actor",
|
|
60
|
-
identifier
|
|
32
|
+
identifier: paths[paths.length - 1]
|
|
61
33
|
};
|
|
62
34
|
}
|
|
63
35
|
});
|
|
@@ -89,11 +61,10 @@ test("handleWebFinger()", async (t) => {
|
|
|
89
61
|
await t.step("no actor dispatcher", async () => {
|
|
90
62
|
const context = createContext(url);
|
|
91
63
|
const request = context.request;
|
|
92
|
-
|
|
64
|
+
assertEquals((await handleWebFinger(request, {
|
|
93
65
|
context,
|
|
94
66
|
onNotFound
|
|
95
|
-
});
|
|
96
|
-
assertEquals(response.status, 404);
|
|
67
|
+
})).status, 404);
|
|
97
68
|
assertEquals(onNotFoundCalled, request);
|
|
98
69
|
});
|
|
99
70
|
onNotFoundCalled = null;
|
|
@@ -113,8 +84,7 @@ test("handleWebFinger()", async (t) => {
|
|
|
113
84
|
const u = new URL(url);
|
|
114
85
|
u.searchParams.set("resource", " invalid ");
|
|
115
86
|
const context = createContext(u);
|
|
116
|
-
const
|
|
117
|
-
const response = await handleWebFinger(request, {
|
|
87
|
+
const response = await handleWebFinger(new Request(u), {
|
|
118
88
|
context,
|
|
119
89
|
actorDispatcher,
|
|
120
90
|
onNotFound
|
|
@@ -220,12 +190,11 @@ test("handleWebFinger()", async (t) => {
|
|
|
220
190
|
u.searchParams.set("resource", "acct:no-one@example.com");
|
|
221
191
|
const context = createContext(u);
|
|
222
192
|
const request = context.request;
|
|
223
|
-
|
|
193
|
+
assertEquals((await handleWebFinger(request, {
|
|
224
194
|
context,
|
|
225
195
|
actorDispatcher,
|
|
226
196
|
onNotFound
|
|
227
|
-
});
|
|
228
|
-
assertEquals(response.status, 404);
|
|
197
|
+
})).status, 404);
|
|
229
198
|
assertEquals(onNotFoundCalled, request);
|
|
230
199
|
});
|
|
231
200
|
onNotFoundCalled = null;
|
|
@@ -521,16 +490,14 @@ test("handleWebFinger()", async (t) => {
|
|
|
521
490
|
onNotFound
|
|
522
491
|
});
|
|
523
492
|
assertEquals(response.status, 200);
|
|
524
|
-
|
|
525
|
-
const expectedWithCustomLinks = {
|
|
493
|
+
assertEquals(await response.json(), {
|
|
526
494
|
...expected,
|
|
527
495
|
links: [...expected.links, {
|
|
528
496
|
rel: "http://ostatus.org/schema/1.0/subscribe",
|
|
529
497
|
template: "https://example.com/follow?acct={uri}"
|
|
530
498
|
}]
|
|
531
|
-
};
|
|
532
|
-
assertEquals(result, expectedWithCustomLinks);
|
|
499
|
+
});
|
|
533
500
|
});
|
|
534
501
|
});
|
|
535
|
-
|
|
536
|
-
|
|
502
|
+
//#endregion
|
|
503
|
+
export {};
|
|
@@ -5,7 +5,6 @@ import { TracerProvider } from "@opentelemetry/api";
|
|
|
5
5
|
import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
6
6
|
|
|
7
7
|
//#region src/sig/key.d.ts
|
|
8
|
-
|
|
9
8
|
/**
|
|
10
9
|
* Generates a key pair which is appropriate for Fedify.
|
|
11
10
|
* @param algorithm The algorithm to use. Currently only RSASSA-PKCS1-v1_5 and
|
|
@@ -238,9 +237,5 @@ interface HttpMessageSignaturesSpecDeterminer {
|
|
|
238
237
|
*/
|
|
239
238
|
rememberSpec(origin: string, spec: HttpMessageSignaturesSpec): void | Promise<void>;
|
|
240
239
|
}
|
|
241
|
-
/**
|
|
242
|
-
* The options for double-knock requests.
|
|
243
|
-
* @since 1.6.0
|
|
244
|
-
*/
|
|
245
240
|
//#endregion
|
|
246
|
-
export {
|
|
241
|
+
export { signRequest as a, FetchKeyResult as c, fetchKey as d, generateCryptoKeyPair as f, VerifyRequestOptions as i, KeyCache as l, HttpMessageSignaturesSpecDeterminer as n, verifyRequest as o, importJwk as p, SignRequestOptions as r, FetchKeyOptions as s, HttpMessageSignaturesSpec as t, exportJwk as u };
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { URLPattern } from "urlpattern-polyfill";
|
|
4
|
-
|
|
1
|
+
import { Temporal } from "@js-temporal/polyfill";
|
|
2
|
+
import "urlpattern-polyfill";
|
|
5
3
|
import { getLogger } from "@logtape/logtape";
|
|
6
4
|
import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
7
5
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -10,121 +8,9 @@ import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
|
|
|
10
8
|
import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
|
|
11
9
|
import { decodeBase64, encodeBase64 } from "byte-encodings/base64";
|
|
12
10
|
import { Item, decodeDict, encodeItem } from "structured-field-values";
|
|
13
|
-
|
|
14
11
|
//#region deno.json
|
|
15
12
|
var name = "@fedify/fedify";
|
|
16
|
-
var version = "2.0.
|
|
17
|
-
var license = "MIT";
|
|
18
|
-
var exports = {
|
|
19
|
-
".": "./src/mod.ts",
|
|
20
|
-
"./compat": "./src/compat/mod.ts",
|
|
21
|
-
"./federation": "./src/federation/mod.ts",
|
|
22
|
-
"./nodeinfo": "./src/nodeinfo/mod.ts",
|
|
23
|
-
"./otel": "./src/otel/mod.ts",
|
|
24
|
-
"./runtime": "./src/runtime/mod.ts",
|
|
25
|
-
"./sig": "./src/sig/mod.ts",
|
|
26
|
-
"./utils": "./src/utils/mod.ts",
|
|
27
|
-
"./vocab": "./src/vocab/mod.ts"
|
|
28
|
-
};
|
|
29
|
-
var imports = {
|
|
30
|
-
"@multiformats/base-x": "npm:@multiformats/base-x@^4.0.1",
|
|
31
|
-
"@std/assert": "jsr:@std/assert@^0.226.0",
|
|
32
|
-
"@std/url": "jsr:@std/url@^0.225.1",
|
|
33
|
-
"asn1js": "npm:asn1js@^3.0.7",
|
|
34
|
-
"fast-check": "npm:fast-check@^3.22.0",
|
|
35
|
-
"fetch-mock": "npm:fetch-mock@^12.5.2",
|
|
36
|
-
"json-canon": "npm:json-canon@^1.0.1",
|
|
37
|
-
"jsonld": "npm:jsonld@^9.0.0",
|
|
38
|
-
"pkijs": "npm:pkijs@^3.3.3",
|
|
39
|
-
"structured-field-values": "npm:structured-field-values@^2.0.4",
|
|
40
|
-
"uri-template-router": "npm:uri-template-router@^1.0.0",
|
|
41
|
-
"url-template": "npm:url-template@^3.1.1"
|
|
42
|
-
};
|
|
43
|
-
var exclude = [
|
|
44
|
-
".test-report.xml",
|
|
45
|
-
"apidoc/",
|
|
46
|
-
"dist/",
|
|
47
|
-
"node_modules/",
|
|
48
|
-
"npm/",
|
|
49
|
-
"pnpm-lock.yaml",
|
|
50
|
-
"src/cfworkers/dist/",
|
|
51
|
-
"src/cfworkers/fixtures/",
|
|
52
|
-
"src/cfworkers/imports.ts",
|
|
53
|
-
"src/cfworkers/README.md",
|
|
54
|
-
"src/cfworkers/server.ts",
|
|
55
|
-
"src/cfworkers/server.js",
|
|
56
|
-
"src/cfworkers/server.js.map"
|
|
57
|
-
];
|
|
58
|
-
var publish = { "exclude": [
|
|
59
|
-
"**/*.test.ts",
|
|
60
|
-
"src/testing/",
|
|
61
|
-
"tsdown.config.ts",
|
|
62
|
-
"scripts/",
|
|
63
|
-
"wrangler.toml"
|
|
64
|
-
] };
|
|
65
|
-
var tasks = {
|
|
66
|
-
"codegen": "deno task -f @fedify/vocab compile",
|
|
67
|
-
"cache": {
|
|
68
|
-
"command": "deno cache src/mod.ts",
|
|
69
|
-
"dependencies": ["codegen"]
|
|
70
|
-
},
|
|
71
|
-
"check": {
|
|
72
|
-
"command": "deno fmt --check && deno lint && deno check src/**/*.ts",
|
|
73
|
-
"dependencies": ["codegen"]
|
|
74
|
-
},
|
|
75
|
-
"test": {
|
|
76
|
-
"command": "deno test --check --doc --allow-read --allow-write --allow-env --unstable-kv --trace-leaks --parallel",
|
|
77
|
-
"dependencies": ["codegen"]
|
|
78
|
-
},
|
|
79
|
-
"coverage": "deno task test --clean --coverage && deno coverage --html coverage",
|
|
80
|
-
"bench": {
|
|
81
|
-
"command": "deno bench --allow-read --allow-write --allow-net --allow-env --allow-run --unstable-kv",
|
|
82
|
-
"dependencies": ["codegen"]
|
|
83
|
-
},
|
|
84
|
-
"apidoc": {
|
|
85
|
-
"command": "deno doc --html --name=Fedify --output=apidoc/ src/mod.ts",
|
|
86
|
-
"dependencies": ["codegen"]
|
|
87
|
-
},
|
|
88
|
-
"publish": {
|
|
89
|
-
"command": "deno publish",
|
|
90
|
-
"dependencies": ["codegen"]
|
|
91
|
-
},
|
|
92
|
-
"pnpm:install": "pnpm install --silent",
|
|
93
|
-
"pnpm:build": {
|
|
94
|
-
"command": "pnpm exec tsdown",
|
|
95
|
-
"dependencies": ["pnpm:build-vocab"]
|
|
96
|
-
},
|
|
97
|
-
"test:node": {
|
|
98
|
-
"command": "cd dist/ && node --test",
|
|
99
|
-
"dependencies": ["pnpm:build"]
|
|
100
|
-
},
|
|
101
|
-
"test:bun": {
|
|
102
|
-
"command": "cd dist/ && bun test --timeout 60000",
|
|
103
|
-
"dependencies": ["pnpm:build"]
|
|
104
|
-
},
|
|
105
|
-
"test:cfworkers": {
|
|
106
|
-
"command": "pnpm exec wrangler deploy --dry-run --outdir src/cfworkers && node --import=tsx src/cfworkers/client.ts",
|
|
107
|
-
"dependencies": ["pnpm:build"]
|
|
108
|
-
},
|
|
109
|
-
"test-all": { "dependencies": [
|
|
110
|
-
"check",
|
|
111
|
-
"test",
|
|
112
|
-
"test:node",
|
|
113
|
-
"test:bun",
|
|
114
|
-
"test:cfworkers"
|
|
115
|
-
] }
|
|
116
|
-
};
|
|
117
|
-
var deno_default = {
|
|
118
|
-
name,
|
|
119
|
-
version,
|
|
120
|
-
license,
|
|
121
|
-
exports,
|
|
122
|
-
imports,
|
|
123
|
-
exclude,
|
|
124
|
-
publish,
|
|
125
|
-
tasks
|
|
126
|
-
};
|
|
127
|
-
|
|
13
|
+
var version = "2.0.9";
|
|
128
14
|
//#endregion
|
|
129
15
|
//#region src/sig/key.ts
|
|
130
16
|
/**
|
|
@@ -140,8 +26,7 @@ function validateCryptoKey(key, type) {
|
|
|
140
26
|
if (!key.extractable) throw new TypeError("The key is not extractable.");
|
|
141
27
|
if (key.algorithm.name !== "RSASSA-PKCS1-v1_5" && key.algorithm.name !== "Ed25519") throw new TypeError("Currently only RSASSA-PKCS1-v1_5 and Ed25519 keys are supported. More algorithms will be added in the future!");
|
|
142
28
|
if (key.algorithm.name === "RSASSA-PKCS1-v1_5") {
|
|
143
|
-
|
|
144
|
-
if (algorithm.hash.name !== "SHA-256") throw new TypeError("For compatibility with the existing Fediverse software (e.g., Mastodon), hash algorithm for RSASSA-PKCS1-v1_5 keys must be SHA-256.");
|
|
29
|
+
if (key.algorithm.hash.name !== "SHA-256") throw new TypeError("For compatibility with the existing Fediverse software (e.g., Mastodon), hash algorithm for RSASSA-PKCS1-v1_5 keys must be SHA-256.");
|
|
145
30
|
}
|
|
146
31
|
}
|
|
147
32
|
/**
|
|
@@ -220,8 +105,7 @@ async function importJwk(jwk, type) {
|
|
|
220
105
|
* @since 1.3.0
|
|
221
106
|
*/
|
|
222
107
|
function fetchKey(keyId, cls, options = {}) {
|
|
223
|
-
const
|
|
224
|
-
const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
|
|
108
|
+
const tracer = (options.tracerProvider ?? trace.getTracerProvider()).getTracer(name, version);
|
|
225
109
|
keyId = typeof keyId === "string" ? new URL(keyId) : keyId;
|
|
226
110
|
return tracer.startActiveSpan("activitypub.fetch_key", {
|
|
227
111
|
kind: SpanKind.CLIENT,
|
|
@@ -277,8 +161,7 @@ async function fetchKeyInternal(keyId, cls, { documentLoader, contextLoader, key
|
|
|
277
161
|
logger.debug("Fetching key {keyId} to verify signature...", { keyId });
|
|
278
162
|
let document;
|
|
279
163
|
try {
|
|
280
|
-
|
|
281
|
-
document = remoteDocument.document;
|
|
164
|
+
document = (await (documentLoader ?? getDocumentLoader())(keyId)).document;
|
|
282
165
|
} catch (_) {
|
|
283
166
|
logger.debug("Failed to fetch key {keyId}.", { keyId });
|
|
284
167
|
await keyCache?.set(cacheKey, null);
|
|
@@ -302,8 +185,8 @@ async function fetchKeyInternal(keyId, cls, { documentLoader, contextLoader, key
|
|
|
302
185
|
contextLoader,
|
|
303
186
|
tracerProvider
|
|
304
187
|
});
|
|
305
|
-
} catch (e
|
|
306
|
-
if (e
|
|
188
|
+
} catch (e) {
|
|
189
|
+
if (e instanceof TypeError) {
|
|
307
190
|
logger.debug("Failed to verify; key {keyId} returned an invalid object.", { keyId });
|
|
308
191
|
await keyCache?.set(cacheKey, null);
|
|
309
192
|
return {
|
|
@@ -311,7 +194,7 @@ async function fetchKeyInternal(keyId, cls, { documentLoader, contextLoader, key
|
|
|
311
194
|
cached: false
|
|
312
195
|
};
|
|
313
196
|
}
|
|
314
|
-
throw e
|
|
197
|
+
throw e;
|
|
315
198
|
}
|
|
316
199
|
}
|
|
317
200
|
let key = null;
|
|
@@ -374,7 +257,6 @@ async function fetchKeyInternal(keyId, cls, { documentLoader, contextLoader, key
|
|
|
374
257
|
cached: false
|
|
375
258
|
};
|
|
376
259
|
}
|
|
377
|
-
|
|
378
260
|
//#endregion
|
|
379
261
|
//#region src/sig/http.ts
|
|
380
262
|
const DEFAULT_MAX_REDIRECTION = 20;
|
|
@@ -389,9 +271,7 @@ const DEFAULT_MAX_REDIRECTION = 20;
|
|
|
389
271
|
*/
|
|
390
272
|
async function signRequest(request, privateKey, keyId, options = {}) {
|
|
391
273
|
validateCryptoKey(privateKey, "private");
|
|
392
|
-
|
|
393
|
-
const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
|
|
394
|
-
return await tracer.startActiveSpan("http_signatures.sign", async (span) => {
|
|
274
|
+
return await (options.tracerProvider ?? trace.getTracerProvider()).getTracer(name, version).startActiveSpan("http_signatures.sign", async (span) => {
|
|
395
275
|
try {
|
|
396
276
|
const spec = options.spec ?? "draft-cavage-http-signatures-12";
|
|
397
277
|
let signed;
|
|
@@ -400,7 +280,7 @@ async function signRequest(request, privateKey, keyId, options = {}) {
|
|
|
400
280
|
if (span.isRecording()) {
|
|
401
281
|
span.setAttribute(ATTR_HTTP_REQUEST_METHOD, signed.method);
|
|
402
282
|
span.setAttribute(ATTR_URL_FULL, signed.url);
|
|
403
|
-
for (const [name
|
|
283
|
+
for (const [name, value] of signed.headers) span.setAttribute(ATTR_HTTP_REQUEST_HEADER(name), value);
|
|
404
284
|
span.setAttribute("http_signatures.key_id", keyId.href);
|
|
405
285
|
}
|
|
406
286
|
return signed;
|
|
@@ -428,8 +308,8 @@ async function signRequestDraft(request, privateKey, keyId, span, currentTime, b
|
|
|
428
308
|
}
|
|
429
309
|
if (!headers.has("Date")) headers.set("Date", currentTime == null ? (/* @__PURE__ */ new Date()).toUTCString() : new Date(currentTime.toString()).toUTCString());
|
|
430
310
|
const serialized = [["(request-target)", `${request.method.toLowerCase()} ${url.pathname}`], ...headers];
|
|
431
|
-
const headerNames = serialized.map(([name
|
|
432
|
-
const message = serialized.map(([name
|
|
311
|
+
const headerNames = serialized.map(([name]) => name);
|
|
312
|
+
const message = serialized.map(([name, value]) => `${name}: ${value.trim()}`).join("\n");
|
|
433
313
|
const signature = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", privateKey, new TextEncoder().encode(message));
|
|
434
314
|
const sigHeader = `keyId="${keyId.href}",algorithm="rsa-sha256",headers="${headerNames.join(" ")}",signature="${encodeBase64(signature)}"`;
|
|
435
315
|
headers.set("Signature", sigHeader);
|
|
@@ -486,9 +366,7 @@ function createRfc9421SignatureBase(request, components, parameters) {
|
|
|
486
366
|
* @returns The formatted signature string.
|
|
487
367
|
*/
|
|
488
368
|
function formatRfc9421Signature(signature, components, parameters) {
|
|
489
|
-
|
|
490
|
-
const signatureValue = `sig1=:${encodeBase64(signature)}:`;
|
|
491
|
-
return [signatureInputValue, signatureValue];
|
|
369
|
+
return [`sig1=("${components.join("\" \"")}");${parameters}`, `sig1=:${encodeBase64(signature)}:`];
|
|
492
370
|
}
|
|
493
371
|
/**
|
|
494
372
|
* Parse RFC 9421 Signature-Input header.
|
|
@@ -618,13 +496,11 @@ const supportedHashAlgorithms = {
|
|
|
618
496
|
* could not be verified.
|
|
619
497
|
*/
|
|
620
498
|
async function verifyRequest(request, options = {}) {
|
|
621
|
-
|
|
622
|
-
const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
|
|
623
|
-
return await tracer.startActiveSpan("http_signatures.verify", async (span) => {
|
|
499
|
+
return await (options.tracerProvider ?? trace.getTracerProvider()).getTracer(name, version).startActiveSpan("http_signatures.verify", async (span) => {
|
|
624
500
|
if (span.isRecording()) {
|
|
625
501
|
span.setAttribute(ATTR_HTTP_REQUEST_METHOD, request.method);
|
|
626
502
|
span.setAttribute(ATTR_URL_FULL, request.url);
|
|
627
|
-
for (const [name
|
|
503
|
+
for (const [name, value] of request.headers) span.setAttribute(ATTR_HTTP_REQUEST_HEADER(name), value);
|
|
628
504
|
}
|
|
629
505
|
try {
|
|
630
506
|
let spec = options.spec;
|
|
@@ -807,11 +683,10 @@ async function verifyRequestDraft(request, span, { documentLoader, contextLoader
|
|
|
807
683
|
logger.debug("Failed to verify; required headers missing in the Signature header: {headers}.", { headers });
|
|
808
684
|
return null;
|
|
809
685
|
}
|
|
810
|
-
const message = headerNames.map((name
|
|
686
|
+
const message = headerNames.map((name) => `${name}: ` + (name === "(request-target)" ? `${request.method.toLowerCase()} ${new URL(request.url).pathname}` : name === "(created)" ? sigValues.created ?? "" : name === "(expires)" ? sigValues.expires ?? "" : name === "host" ? request.headers.get("host") ?? new URL(request.url).host : request.headers.get(name))).join("\n");
|
|
811
687
|
const sig = decodeBase64(signature);
|
|
812
688
|
span?.setAttribute("http_signatures.signature", encodeHex(sig));
|
|
813
|
-
|
|
814
|
-
if (!verified) {
|
|
689
|
+
if (!await crypto.subtle.verify("RSASSA-PKCS1-v1_5", key.publicKey, sig, new TextEncoder().encode(message))) {
|
|
815
690
|
if (cached) {
|
|
816
691
|
logger.debug("Failed to verify with the cached key {keyId}; signature {signature} is invalid. Retrying with the freshly fetched key...", {
|
|
817
692
|
keyId,
|
|
@@ -825,7 +700,7 @@ async function verifyRequestDraft(request, span, { documentLoader, contextLoader
|
|
|
825
700
|
currentTime,
|
|
826
701
|
keyCache: {
|
|
827
702
|
get: () => Promise.resolve(void 0),
|
|
828
|
-
set: async (keyId
|
|
703
|
+
set: async (keyId, key) => await keyCache?.set(keyId, key)
|
|
829
704
|
}
|
|
830
705
|
});
|
|
831
706
|
}
|
|
@@ -975,9 +850,7 @@ async function verifyRequestRfc9421(request, span, { documentLoader, contextLoad
|
|
|
975
850
|
logger.debug("Failed to verify; Content-Digest header required but not found.", { components: sigInput.components });
|
|
976
851
|
continue;
|
|
977
852
|
}
|
|
978
|
-
|
|
979
|
-
const digestValid = await verifyRfc9421ContentDigest(contentDigestHeader, body);
|
|
980
|
-
if (!digestValid) {
|
|
853
|
+
if (!await verifyRfc9421ContentDigest(contentDigestHeader, await request.arrayBuffer())) {
|
|
981
854
|
logger.debug("Failed to verify; Content-Digest verification failed.", { contentDigest: contentDigestHeader });
|
|
982
855
|
continue;
|
|
983
856
|
}
|
|
@@ -1023,8 +896,7 @@ async function verifyRequestRfc9421(request, span, { documentLoader, contextLoad
|
|
|
1023
896
|
const signatureBaseBytes = new TextEncoder().encode(signatureBase);
|
|
1024
897
|
span?.setAttribute("http_signatures.signature", encodeHex(sigBytes));
|
|
1025
898
|
try {
|
|
1026
|
-
|
|
1027
|
-
if (verified) {
|
|
899
|
+
if (await crypto.subtle.verify(algorithm, key.publicKey, sigBytes.slice(), signatureBaseBytes)) {
|
|
1028
900
|
validKey = key;
|
|
1029
901
|
break;
|
|
1030
902
|
} else if (cached) {
|
|
@@ -1036,7 +908,7 @@ async function verifyRequestRfc9421(request, span, { documentLoader, contextLoad
|
|
|
1036
908
|
currentTime,
|
|
1037
909
|
keyCache: {
|
|
1038
910
|
get: () => Promise.resolve(void 0),
|
|
1039
|
-
set: async (keyId, key
|
|
911
|
+
set: async (keyId, key) => await keyCache?.set(keyId, key)
|
|
1040
912
|
},
|
|
1041
913
|
spec: "rfc9421"
|
|
1042
914
|
});
|
|
@@ -1109,8 +981,7 @@ async function doubleKnockInternal(request, identity, options, redirected = 0, v
|
|
|
1109
981
|
});
|
|
1110
982
|
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
1111
983
|
if (redirected >= DEFAULT_MAX_REDIRECTION) throw new FetchError(request.url, `Too many redirections (${redirected + 1})`);
|
|
1112
|
-
const
|
|
1113
|
-
const redirectRequest = createRedirectRequest(request, location, body);
|
|
984
|
+
const redirectRequest = createRedirectRequest(request, response.headers.get("Location"), body);
|
|
1114
985
|
if (visited.has(redirectRequest.url)) throw new FetchError(request.url, `Redirect loop detected: ${redirectRequest.url}`);
|
|
1115
986
|
return doubleKnockInternal(redirectRequest, identity, {
|
|
1116
987
|
...options,
|
|
@@ -1140,8 +1011,7 @@ async function doubleKnockInternal(request, identity, options, redirected = 0, v
|
|
|
1140
1011
|
});
|
|
1141
1012
|
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
1142
1013
|
if (redirected >= DEFAULT_MAX_REDIRECTION) throw new FetchError(request.url, `Too many redirections (${redirected + 1})`);
|
|
1143
|
-
const
|
|
1144
|
-
const redirectRequest = createRedirectRequest(request, location, body);
|
|
1014
|
+
const redirectRequest = createRedirectRequest(request, response.headers.get("Location"), body);
|
|
1145
1015
|
if (visited.has(redirectRequest.url)) throw new FetchError(request.url, `Redirect loop detected: ${redirectRequest.url}`);
|
|
1146
1016
|
return doubleKnockInternal(redirectRequest, identity, {
|
|
1147
1017
|
...options,
|
|
@@ -1178,6 +1048,5 @@ function timingSafeEqual(a, b) {
|
|
|
1178
1048
|
result |= lenA ^ lenB;
|
|
1179
1049
|
return result === 0;
|
|
1180
1050
|
}
|
|
1181
|
-
|
|
1182
1051
|
//#endregion
|
|
1183
|
-
export {
|
|
1052
|
+
export { fetchKey as a, validateCryptoKey as c, exportJwk as i, name as l, signRequest as n, generateCryptoKeyPair as o, verifyRequest as r, importJwk as s, doubleKnock as t, version as u };
|
|
@@ -3,7 +3,6 @@ import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
|
3
3
|
import { TracerProvider } from "@opentelemetry/api";
|
|
4
4
|
|
|
5
5
|
//#region src/sig/key.d.ts
|
|
6
|
-
|
|
7
6
|
/**
|
|
8
7
|
* Generates a key pair which is appropriate for Fedify.
|
|
9
8
|
* @param algorithm The algorithm to use. Currently only RSASSA-PKCS1-v1_5 and
|
|
@@ -236,9 +235,5 @@ interface HttpMessageSignaturesSpecDeterminer {
|
|
|
236
235
|
*/
|
|
237
236
|
rememberSpec(origin: string, spec: HttpMessageSignaturesSpec): void | Promise<void>;
|
|
238
237
|
}
|
|
239
|
-
/**
|
|
240
|
-
* The options for double-knock requests.
|
|
241
|
-
* @since 1.6.0
|
|
242
|
-
*/
|
|
243
238
|
//#endregion
|
|
244
|
-
export {
|
|
239
|
+
export { signRequest as a, FetchKeyResult as c, fetchKey as d, generateCryptoKeyPair as f, VerifyRequestOptions as i, KeyCache as l, HttpMessageSignaturesSpecDeterminer as n, verifyRequest as o, importJwk as p, SignRequestOptions as r, FetchKeyOptions as s, HttpMessageSignaturesSpec as t, exportJwk as u };
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { deno_default } from "./deno-4w047OFk.js";
|
|
7
|
-
import { fetchKey, validateCryptoKey } from "./key-D7Y_J9kt.js";
|
|
1
|
+
import { Temporal } from "@js-temporal/polyfill";
|
|
2
|
+
import "urlpattern-polyfill";
|
|
3
|
+
globalThis.addEventListener = () => {};
|
|
4
|
+
import { n as version, t as name } from "./deno-CuVDEdyj.mjs";
|
|
5
|
+
import { a as validateCryptoKey, n as fetchKey } from "./key-DzJf84o7.mjs";
|
|
8
6
|
import { CryptographicKey } from "@fedify/vocab";
|
|
7
|
+
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
9
8
|
import { FetchError } from "@fedify/vocab-runtime";
|
|
10
9
|
import { getLogger } from "@logtape/logtape";
|
|
11
|
-
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
12
10
|
import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
|
|
13
11
|
import { decodeBase64, encodeBase64 } from "byte-encodings/base64";
|
|
14
12
|
import { encodeHex } from "byte-encodings/hex";
|
|
15
13
|
import { Item, decodeDict, encodeItem } from "structured-field-values";
|
|
16
|
-
|
|
17
14
|
//#region src/sig/http.ts
|
|
18
15
|
const DEFAULT_MAX_REDIRECTION = 20;
|
|
19
16
|
/**
|
|
@@ -27,9 +24,7 @@ const DEFAULT_MAX_REDIRECTION = 20;
|
|
|
27
24
|
*/
|
|
28
25
|
async function signRequest(request, privateKey, keyId, options = {}) {
|
|
29
26
|
validateCryptoKey(privateKey, "private");
|
|
30
|
-
|
|
31
|
-
const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
|
|
32
|
-
return await tracer.startActiveSpan("http_signatures.sign", async (span) => {
|
|
27
|
+
return await (options.tracerProvider ?? trace.getTracerProvider()).getTracer(name, version).startActiveSpan("http_signatures.sign", async (span) => {
|
|
33
28
|
try {
|
|
34
29
|
const spec = options.spec ?? "draft-cavage-http-signatures-12";
|
|
35
30
|
let signed;
|
|
@@ -124,9 +119,7 @@ function createRfc9421SignatureBase(request, components, parameters) {
|
|
|
124
119
|
* @returns The formatted signature string.
|
|
125
120
|
*/
|
|
126
121
|
function formatRfc9421Signature(signature, components, parameters) {
|
|
127
|
-
|
|
128
|
-
const signatureValue = `sig1=:${encodeBase64(signature)}:`;
|
|
129
|
-
return [signatureInputValue, signatureValue];
|
|
122
|
+
return [`sig1=("${components.join("\" \"")}");${parameters}`, `sig1=:${encodeBase64(signature)}:`];
|
|
130
123
|
}
|
|
131
124
|
/**
|
|
132
125
|
* Parse RFC 9421 Signature-Input header.
|
|
@@ -256,9 +249,7 @@ const supportedHashAlgorithms = {
|
|
|
256
249
|
* could not be verified.
|
|
257
250
|
*/
|
|
258
251
|
async function verifyRequest(request, options = {}) {
|
|
259
|
-
|
|
260
|
-
const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
|
|
261
|
-
return await tracer.startActiveSpan("http_signatures.verify", async (span) => {
|
|
252
|
+
return await (options.tracerProvider ?? trace.getTracerProvider()).getTracer(name, version).startActiveSpan("http_signatures.verify", async (span) => {
|
|
262
253
|
if (span.isRecording()) {
|
|
263
254
|
span.setAttribute(ATTR_HTTP_REQUEST_METHOD, request.method);
|
|
264
255
|
span.setAttribute(ATTR_URL_FULL, request.url);
|
|
@@ -448,8 +439,7 @@ async function verifyRequestDraft(request, span, { documentLoader, contextLoader
|
|
|
448
439
|
const message = headerNames.map((name) => `${name}: ` + (name === "(request-target)" ? `${request.method.toLowerCase()} ${new URL(request.url).pathname}` : name === "(created)" ? sigValues.created ?? "" : name === "(expires)" ? sigValues.expires ?? "" : name === "host" ? request.headers.get("host") ?? new URL(request.url).host : request.headers.get(name))).join("\n");
|
|
449
440
|
const sig = decodeBase64(signature);
|
|
450
441
|
span?.setAttribute("http_signatures.signature", encodeHex(sig));
|
|
451
|
-
|
|
452
|
-
if (!verified) {
|
|
442
|
+
if (!await crypto.subtle.verify("RSASSA-PKCS1-v1_5", key.publicKey, sig, new TextEncoder().encode(message))) {
|
|
453
443
|
if (cached) {
|
|
454
444
|
logger.debug("Failed to verify with the cached key {keyId}; signature {signature} is invalid. Retrying with the freshly fetched key...", {
|
|
455
445
|
keyId,
|
|
@@ -463,7 +453,7 @@ async function verifyRequestDraft(request, span, { documentLoader, contextLoader
|
|
|
463
453
|
currentTime,
|
|
464
454
|
keyCache: {
|
|
465
455
|
get: () => Promise.resolve(void 0),
|
|
466
|
-
set: async (keyId
|
|
456
|
+
set: async (keyId, key) => await keyCache?.set(keyId, key)
|
|
467
457
|
}
|
|
468
458
|
});
|
|
469
459
|
}
|
|
@@ -613,9 +603,7 @@ async function verifyRequestRfc9421(request, span, { documentLoader, contextLoad
|
|
|
613
603
|
logger.debug("Failed to verify; Content-Digest header required but not found.", { components: sigInput.components });
|
|
614
604
|
continue;
|
|
615
605
|
}
|
|
616
|
-
|
|
617
|
-
const digestValid = await verifyRfc9421ContentDigest(contentDigestHeader, body);
|
|
618
|
-
if (!digestValid) {
|
|
606
|
+
if (!await verifyRfc9421ContentDigest(contentDigestHeader, await request.arrayBuffer())) {
|
|
619
607
|
logger.debug("Failed to verify; Content-Digest verification failed.", { contentDigest: contentDigestHeader });
|
|
620
608
|
continue;
|
|
621
609
|
}
|
|
@@ -661,8 +649,7 @@ async function verifyRequestRfc9421(request, span, { documentLoader, contextLoad
|
|
|
661
649
|
const signatureBaseBytes = new TextEncoder().encode(signatureBase);
|
|
662
650
|
span?.setAttribute("http_signatures.signature", encodeHex(sigBytes));
|
|
663
651
|
try {
|
|
664
|
-
|
|
665
|
-
if (verified) {
|
|
652
|
+
if (await crypto.subtle.verify(algorithm, key.publicKey, sigBytes.slice(), signatureBaseBytes)) {
|
|
666
653
|
validKey = key;
|
|
667
654
|
break;
|
|
668
655
|
} else if (cached) {
|
|
@@ -674,7 +661,7 @@ async function verifyRequestRfc9421(request, span, { documentLoader, contextLoad
|
|
|
674
661
|
currentTime,
|
|
675
662
|
keyCache: {
|
|
676
663
|
get: () => Promise.resolve(void 0),
|
|
677
|
-
set: async (keyId, key
|
|
664
|
+
set: async (keyId, key) => await keyCache?.set(keyId, key)
|
|
678
665
|
},
|
|
679
666
|
spec: "rfc9421"
|
|
680
667
|
});
|
|
@@ -747,8 +734,7 @@ async function doubleKnockInternal(request, identity, options, redirected = 0, v
|
|
|
747
734
|
});
|
|
748
735
|
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
749
736
|
if (redirected >= DEFAULT_MAX_REDIRECTION) throw new FetchError(request.url, `Too many redirections (${redirected + 1})`);
|
|
750
|
-
const
|
|
751
|
-
const redirectRequest = createRedirectRequest(request, location, body);
|
|
737
|
+
const redirectRequest = createRedirectRequest(request, response.headers.get("Location"), body);
|
|
752
738
|
if (visited.has(redirectRequest.url)) throw new FetchError(request.url, `Redirect loop detected: ${redirectRequest.url}`);
|
|
753
739
|
return doubleKnockInternal(redirectRequest, identity, {
|
|
754
740
|
...options,
|
|
@@ -778,8 +764,7 @@ async function doubleKnockInternal(request, identity, options, redirected = 0, v
|
|
|
778
764
|
});
|
|
779
765
|
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
780
766
|
if (redirected >= DEFAULT_MAX_REDIRECTION) throw new FetchError(request.url, `Too many redirections (${redirected + 1})`);
|
|
781
|
-
const
|
|
782
|
-
const redirectRequest = createRedirectRequest(request, location, body);
|
|
767
|
+
const redirectRequest = createRedirectRequest(request, response.headers.get("Location"), body);
|
|
783
768
|
if (visited.has(redirectRequest.url)) throw new FetchError(request.url, `Redirect loop detected: ${redirectRequest.url}`);
|
|
784
769
|
return doubleKnockInternal(redirectRequest, identity, {
|
|
785
770
|
...options,
|
|
@@ -816,6 +801,5 @@ function timingSafeEqual(a, b) {
|
|
|
816
801
|
result |= lenA ^ lenB;
|
|
817
802
|
return result === 0;
|
|
818
803
|
}
|
|
819
|
-
|
|
820
804
|
//#endregion
|
|
821
|
-
export {
|
|
805
|
+
export { parseRfc9421Signature as a, timingSafeEqual as c, formatRfc9421SignatureParameters as i, verifyRequest as l, doubleKnock as n, parseRfc9421SignatureInput as o, formatRfc9421Signature as r, signRequest as s, createRfc9421SignatureBase as t };
|