Loading CHANGES.md +9 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,14 @@ To be released. - `new Question()` constructor now accepts `voters` option. - `Question.clone()` method now accepts `voters` option. - HTTP Signatures verficiation now can be optionally skipped for the sake of testing. [[#110]] - The type of `CreateFederationOptions.signatureTimeWindow` property became `Temporal.DurationLike | false` (was `Temporal.DurationLike`). - The type of `VerifyRequestOptions.timeWindow` property became `Temporal.DurationLike | false` (was `Temporal.DurationLike`). - Removed the singular actor key pair dispatcher APIs which were deprecated in version 0.10.0. Loading Loading @@ -49,6 +57,7 @@ To be released. - `["fedify", "webfinger", "server"]` [#69]: https://github.com/dahlia/fedify/issues/69 [#110]: https://github.com/dahlia/fedify/issues/110 Version 0.12.0 Loading src/federation/handler.ts +1 −1 Original line number Diff line number Diff line Loading @@ -328,7 +328,7 @@ export interface InboxHandlerParameters<TContextData> { inboxListeners?: InboxListenerSet<TContextData>; inboxErrorHandler?: InboxErrorHandler<TContextData>; onNotFound(request: Request): Response | Promise<Response>; signatureTimeWindow: Temporal.DurationLike; signatureTimeWindow: Temporal.DurationLike | false; } export async function handleInbox<TContextData>( Loading src/federation/middleware.ts +6 −4 Original line number Diff line number Diff line Loading @@ -132,10 +132,12 @@ export interface CreateFederationOptions { /** * The time window for verifying the signature of incoming requests. If the * request is older or newer than this window, it is rejected. By default, * the window is a minute. * request is older or newer than this window, it is rejected. Or if it is * `false`, the request's timestamp is not checked at all. * * By default, the window is a minute. */ signatureTimeWindow?: Temporal.DurationLike; signatureTimeWindow?: Temporal.DurationLike | false; /** * The retry policy for sending activities to recipients' inboxes. Loading Loading @@ -617,7 +619,7 @@ class FederationImpl<TContextData> implements Federation<TContextData> { contextLoader: DocumentLoader; authenticatedDocumentLoaderFactory: AuthenticatedDocumentLoaderFactory; onOutboxError?: OutboxErrorHandler; signatureTimeWindow: Temporal.DurationLike; signatureTimeWindow: Temporal.DurationLike | false; outboxRetryPolicy: RetryPolicy; inboxRetryPolicy: RetryPolicy; Loading src/sig/http.test.ts +24 −0 Original line number Diff line number Diff line Loading @@ -188,4 +188,28 @@ test("verifyRequest()", async () => { ), null, ); assertEquals( await verifyRequest( request, { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader, currentTime: Temporal.Instant.from("2024-01-01T00:00:00.0000Z"), timeWindow: false, }, ), rsaPublicKey1, ); assertEquals( await verifyRequest( request, { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader, currentTime: Temporal.Instant.from("2025-01-01T00:00:00.0000Z"), timeWindow: false, }, ), rsaPublicKey1, ); }); src/sig/http.ts +18 −14 Original line number Diff line number Diff line Loading @@ -85,9 +85,11 @@ export interface VerifyRequestOptions { /** * The time window to allow for the request date. The actual time window is * twice the value of this option, with the current time as the center. * Or if it is `false`, no time check is performed. * * A minute by default. */ timeWindow?: Temporal.DurationLike; timeWindow?: Temporal.DurationLike | false; /** * The current time. If not specified, the current time is used. This is Loading Loading @@ -193,6 +195,7 @@ export async function verifyRequest( } const date = Temporal.Instant.from(new Date(dateHeader).toISOString()); const now = currentTime ?? Temporal.Now.instant(); if (timeWindow !== false) { const tw: Temporal.DurationLike = timeWindow ?? { minutes: 1 }; if (Temporal.Instant.compare(date, now.add(tw)) > 0) { logger.debug( Loading @@ -207,6 +210,7 @@ export async function verifyRequest( ); return null; } } const sigValues = Object.fromEntries( sigHeader.split(",").map((pair) => pair.match(/^\s*([A-Za-z]+)="([^"]*)"\s*$/) Loading Loading
CHANGES.md +9 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,14 @@ To be released. - `new Question()` constructor now accepts `voters` option. - `Question.clone()` method now accepts `voters` option. - HTTP Signatures verficiation now can be optionally skipped for the sake of testing. [[#110]] - The type of `CreateFederationOptions.signatureTimeWindow` property became `Temporal.DurationLike | false` (was `Temporal.DurationLike`). - The type of `VerifyRequestOptions.timeWindow` property became `Temporal.DurationLike | false` (was `Temporal.DurationLike`). - Removed the singular actor key pair dispatcher APIs which were deprecated in version 0.10.0. Loading Loading @@ -49,6 +57,7 @@ To be released. - `["fedify", "webfinger", "server"]` [#69]: https://github.com/dahlia/fedify/issues/69 [#110]: https://github.com/dahlia/fedify/issues/110 Version 0.12.0 Loading
src/federation/handler.ts +1 −1 Original line number Diff line number Diff line Loading @@ -328,7 +328,7 @@ export interface InboxHandlerParameters<TContextData> { inboxListeners?: InboxListenerSet<TContextData>; inboxErrorHandler?: InboxErrorHandler<TContextData>; onNotFound(request: Request): Response | Promise<Response>; signatureTimeWindow: Temporal.DurationLike; signatureTimeWindow: Temporal.DurationLike | false; } export async function handleInbox<TContextData>( Loading
src/federation/middleware.ts +6 −4 Original line number Diff line number Diff line Loading @@ -132,10 +132,12 @@ export interface CreateFederationOptions { /** * The time window for verifying the signature of incoming requests. If the * request is older or newer than this window, it is rejected. By default, * the window is a minute. * request is older or newer than this window, it is rejected. Or if it is * `false`, the request's timestamp is not checked at all. * * By default, the window is a minute. */ signatureTimeWindow?: Temporal.DurationLike; signatureTimeWindow?: Temporal.DurationLike | false; /** * The retry policy for sending activities to recipients' inboxes. Loading Loading @@ -617,7 +619,7 @@ class FederationImpl<TContextData> implements Federation<TContextData> { contextLoader: DocumentLoader; authenticatedDocumentLoaderFactory: AuthenticatedDocumentLoaderFactory; onOutboxError?: OutboxErrorHandler; signatureTimeWindow: Temporal.DurationLike; signatureTimeWindow: Temporal.DurationLike | false; outboxRetryPolicy: RetryPolicy; inboxRetryPolicy: RetryPolicy; Loading
src/sig/http.test.ts +24 −0 Original line number Diff line number Diff line Loading @@ -188,4 +188,28 @@ test("verifyRequest()", async () => { ), null, ); assertEquals( await verifyRequest( request, { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader, currentTime: Temporal.Instant.from("2024-01-01T00:00:00.0000Z"), timeWindow: false, }, ), rsaPublicKey1, ); assertEquals( await verifyRequest( request, { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader, currentTime: Temporal.Instant.from("2025-01-01T00:00:00.0000Z"), timeWindow: false, }, ), rsaPublicKey1, ); });
src/sig/http.ts +18 −14 Original line number Diff line number Diff line Loading @@ -85,9 +85,11 @@ export interface VerifyRequestOptions { /** * The time window to allow for the request date. The actual time window is * twice the value of this option, with the current time as the center. * Or if it is `false`, no time check is performed. * * A minute by default. */ timeWindow?: Temporal.DurationLike; timeWindow?: Temporal.DurationLike | false; /** * The current time. If not specified, the current time is used. This is Loading Loading @@ -193,6 +195,7 @@ export async function verifyRequest( } const date = Temporal.Instant.from(new Date(dateHeader).toISOString()); const now = currentTime ?? Temporal.Now.instant(); if (timeWindow !== false) { const tw: Temporal.DurationLike = timeWindow ?? { minutes: 1 }; if (Temporal.Instant.compare(date, now.add(tw)) > 0) { logger.debug( Loading @@ -207,6 +210,7 @@ export async function verifyRequest( ); return null; } } const sigValues = Object.fromEntries( sigHeader.split(",").map((pair) => pair.match(/^\s*([A-Za-z]+)="([^"]*)"\s*$/) Loading