@fedify/fedify 0.10.0-dev.203 → 0.10.0-dev.205
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/CHANGES.md +5 -0
- package/esm/federation/handler.js +26 -16
- package/esm/sig/proof.js +9 -5
- package/package.json +1 -1
- package/types/federation/handler.d.ts.map +1 -1
- package/types/sig/proof.d.ts +8 -4
- package/types/sig/proof.d.ts.map +1 -1
package/CHANGES.md
CHANGED
|
@@ -85,6 +85,11 @@ To be released.
|
|
|
85
85
|
|
|
86
86
|
- Implemented Object Integrity Proofs. [[FEP-8b32], [#54]]
|
|
87
87
|
|
|
88
|
+
- If there are any Ed25519 key pairs, the `Context.sendActivity()` and
|
|
89
|
+
`Federation.sendActivity()` methods now make Object Integrity Proofs
|
|
90
|
+
for the activity to be sent.
|
|
91
|
+
- If the incoming activity has Object Integrity Proofs, the inbox listener
|
|
92
|
+
now verifies them and ignores HTTP Signatures (if any).
|
|
88
93
|
- Added `signObject()` function.
|
|
89
94
|
- Added `SignObjectOptions` interface.
|
|
90
95
|
- Added `createProof()` function.
|
|
@@ -3,6 +3,7 @@ import { getLogger } from "@logtape/logtape";
|
|
|
3
3
|
import { accepts } from "../deps/jsr.io/@std/http/0.224.4/negotiation.js";
|
|
4
4
|
import { verifyRequest } from "../sig/http.js";
|
|
5
5
|
import { doesActorOwnKey } from "../sig/owner.js";
|
|
6
|
+
import { verifyObject } from "../sig/proof.js";
|
|
6
7
|
import { Activity, Link, Object, OrderedCollection, OrderedCollectionPage, } from "../vocab/vocab.js";
|
|
7
8
|
export function acceptsJsonLd(request) {
|
|
8
9
|
const types = accepts(request);
|
|
@@ -175,21 +176,9 @@ export async function handleInbox(request, { handle, context, kv, kvPrefix, acto
|
|
|
175
176
|
return await onNotFound(request);
|
|
176
177
|
}
|
|
177
178
|
}
|
|
178
|
-
const key = await verifyRequest(request, {
|
|
179
|
-
...context,
|
|
180
|
-
timeWindow: signatureTimeWindow,
|
|
181
|
-
});
|
|
182
|
-
if (key == null) {
|
|
183
|
-
logger.error("Failed to verify the request signature.", { handle });
|
|
184
|
-
const response = new Response("Failed to verify the request signature.", {
|
|
185
|
-
status: 401,
|
|
186
|
-
headers: { "Content-Type": "text/plain; charset=utf-8" },
|
|
187
|
-
});
|
|
188
|
-
return response;
|
|
189
|
-
}
|
|
190
179
|
let json;
|
|
191
180
|
try {
|
|
192
|
-
json = await request.json();
|
|
181
|
+
json = await request.clone().json();
|
|
193
182
|
}
|
|
194
183
|
catch (error) {
|
|
195
184
|
logger.error("Failed to parse JSON:\n{error}", { handle, error });
|
|
@@ -201,7 +190,7 @@ export async function handleInbox(request, { handle, context, kv, kvPrefix, acto
|
|
|
201
190
|
}
|
|
202
191
|
let activity;
|
|
203
192
|
try {
|
|
204
|
-
activity = await Activity
|
|
193
|
+
activity = await verifyObject(Activity, json, context);
|
|
205
194
|
}
|
|
206
195
|
catch (error) {
|
|
207
196
|
logger.error("Failed to parse activity:\n{error}", { handle, json, error });
|
|
@@ -211,6 +200,23 @@ export async function handleInbox(request, { handle, context, kv, kvPrefix, acto
|
|
|
211
200
|
headers: { "Content-Type": "text/plain; charset=utf-8" },
|
|
212
201
|
});
|
|
213
202
|
}
|
|
203
|
+
let httpSigKey = null;
|
|
204
|
+
if (activity == null) {
|
|
205
|
+
const key = await verifyRequest(request, {
|
|
206
|
+
...context,
|
|
207
|
+
timeWindow: signatureTimeWindow,
|
|
208
|
+
});
|
|
209
|
+
if (key == null) {
|
|
210
|
+
logger.error("Failed to verify the request signature.", { handle });
|
|
211
|
+
const response = new Response("Failed to verify the request signature.", {
|
|
212
|
+
status: 401,
|
|
213
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" },
|
|
214
|
+
});
|
|
215
|
+
return response;
|
|
216
|
+
}
|
|
217
|
+
httpSigKey = key;
|
|
218
|
+
activity = await Activity.fromJsonLd(json, context);
|
|
219
|
+
}
|
|
214
220
|
const cacheKey = activity.id == null
|
|
215
221
|
? null
|
|
216
222
|
: [...kvPrefix, activity.id.href];
|
|
@@ -235,8 +241,12 @@ export async function handleInbox(request, { handle, context, kv, kvPrefix, acto
|
|
|
235
241
|
});
|
|
236
242
|
return response;
|
|
237
243
|
}
|
|
238
|
-
if (!await doesActorOwnKey(activity,
|
|
239
|
-
logger.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
|
|
244
|
+
if (httpSigKey != null && !await doesActorOwnKey(activity, httpSigKey, context)) {
|
|
245
|
+
logger.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
|
|
246
|
+
activity: json,
|
|
247
|
+
keyId: httpSigKey.id?.href,
|
|
248
|
+
actorId: activity.actorId.href,
|
|
249
|
+
});
|
|
240
250
|
const response = new Response("The signer and the actor do not match.", {
|
|
241
251
|
status: 401,
|
|
242
252
|
headers: { "Content-Type": "text/plain; charset=utf-8" },
|
package/esm/sig/proof.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as dntShim from "../_dnt.shims.js";
|
|
2
2
|
// @ts-ignore: json-canon is not typed
|
|
3
3
|
import serialize from "json-canon";
|
|
4
|
-
import { DataIntegrityProof
|
|
4
|
+
import { DataIntegrityProof } from "../vocab/vocab.js";
|
|
5
5
|
import { fetchKey, validateCryptoKey } from "./key.js";
|
|
6
6
|
import { Activity, Multikey } from "../vocab/mod.js";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
@@ -148,17 +148,21 @@ export async function verifyProof(jsonLd, proof, options = {}) {
|
|
|
148
148
|
* Verifies the given object. It will verify all the proofs in the object,
|
|
149
149
|
* and succeed only if all the proofs are valid and all attributions and
|
|
150
150
|
* actors are authenticated by the proofs.
|
|
151
|
+
* @typeParam T The type of the object to verify.
|
|
152
|
+
* @param cls The class of the object to verify. It must be a subclass of
|
|
153
|
+
* the {@link Object}.
|
|
151
154
|
* @param jsonLd The JSON-LD object to verify. It's assumed that the object
|
|
152
|
-
* is a compacted JSON-LD representation of
|
|
153
|
-
* with `@context`.
|
|
155
|
+
* is a compacted JSON-LD representation of a `T` with `@context`.
|
|
154
156
|
* @param options Additional options. See also {@link VerifyObjectOptions}.
|
|
155
157
|
* @returns The object if it's verified, or `null` if it's not.
|
|
156
158
|
* @throws {TypeError} If the object is invalid or unsupported.
|
|
157
159
|
* @since 0.10.0
|
|
158
160
|
*/
|
|
159
|
-
export async function verifyObject(
|
|
161
|
+
export async function verifyObject(
|
|
162
|
+
// deno-lint-ignore no-explicit-any
|
|
163
|
+
cls, jsonLd, options = {}) {
|
|
160
164
|
const logger = getLogger(["fedify", "sig", "proof"]);
|
|
161
|
-
const object = await
|
|
165
|
+
const object = await cls.fromJsonLd(jsonLd, options);
|
|
162
166
|
const attributions = new Set(object.attributionIds.map((uri) => uri.href));
|
|
163
167
|
if (object instanceof Activity) {
|
|
164
168
|
for (const uri of object.actorIds)
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/federation/handler.ts"],"names":[],"mappings":";;AAAA,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/federation/handler.ts"],"names":[],"mappings":"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"}
|
package/types/sig/proof.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import * as dntShim from "../_dnt.shims.js";
|
|
3
3
|
import type { DocumentLoader } from "../runtime/docloader.js";
|
|
4
|
-
import { DataIntegrityProof, Object } from "../vocab/vocab.js";
|
|
4
|
+
import { DataIntegrityProof, type Object } from "../vocab/vocab.js";
|
|
5
5
|
import { Multikey } from "../vocab/mod.js";
|
|
6
6
|
/**
|
|
7
7
|
* Options for {@link createProof}.
|
|
@@ -89,13 +89,17 @@ export interface VerifyObjectOptions extends VerifyProofOptions {
|
|
|
89
89
|
* Verifies the given object. It will verify all the proofs in the object,
|
|
90
90
|
* and succeed only if all the proofs are valid and all attributions and
|
|
91
91
|
* actors are authenticated by the proofs.
|
|
92
|
+
* @typeParam T The type of the object to verify.
|
|
93
|
+
* @param cls The class of the object to verify. It must be a subclass of
|
|
94
|
+
* the {@link Object}.
|
|
92
95
|
* @param jsonLd The JSON-LD object to verify. It's assumed that the object
|
|
93
|
-
* is a compacted JSON-LD representation of
|
|
94
|
-
* with `@context`.
|
|
96
|
+
* is a compacted JSON-LD representation of a `T` with `@context`.
|
|
95
97
|
* @param options Additional options. See also {@link VerifyObjectOptions}.
|
|
96
98
|
* @returns The object if it's verified, or `null` if it's not.
|
|
97
99
|
* @throws {TypeError} If the object is invalid or unsupported.
|
|
98
100
|
* @since 0.10.0
|
|
99
101
|
*/
|
|
100
|
-
export declare function verifyObject(
|
|
102
|
+
export declare function verifyObject<T extends Object>(cls: (new (...args: any[]) => T) & {
|
|
103
|
+
fromJsonLd(jsonLd: unknown, options: VerifyObjectOptions): Promise<T>;
|
|
104
|
+
}, jsonLd: unknown, options?: VerifyObjectOptions): Promise<T | null>;
|
|
101
105
|
//# sourceMappingURL=proof.d.ts.map
|
package/types/sig/proof.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../../src/sig/proof.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAG5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../../src/sig/proof.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAG5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,EAAY,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAKrD;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,aAAa,CAAC,EAAE,cAAc,CAAC;IAE/B;;OAEG;IACH,OAAO,CAAC,EACJ,MAAM,GACN,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IAExC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;CACpC;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,OAAO,CAAC,SAAS,EAC7B,KAAK,EAAE,GAAG,EACV,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,GAAE,kBAAuB,GAC3D,OAAO,CAAC,kBAAkB,CAAC,CA2C7B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,CAAC,SAAS,MAAM,EAC/C,MAAM,EAAE,CAAC,EACT,UAAU,EAAE,OAAO,CAAC,SAAS,EAC7B,KAAK,EAAE,GAAG,EACV,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,aAAa,CAAC,EAAE,cAAc,CAAC;IAE/B;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,kBAAkB,EACzB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAqE1B;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAoB,SAAQ,kBAAkB;CAC9D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS,MAAM,EAEjD,GAAG,EAAE,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,GAAG;IACjC,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACvE,EACD,MAAM,EAAE,OAAO,EACf,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CA2BnB"}
|