diff --git a/packages/backend/src/queue/processors/inbox.ts b/packages/backend/src/queue/processors/inbox.ts index 51652357f..033f3413b 100644 --- a/packages/backend/src/queue/processors/inbox.ts +++ b/packages/backend/src/queue/processors/inbox.ts @@ -95,11 +95,25 @@ export default async (job: Bull.Job): Promise => { } // HTTP-Signatureの検証 - const httpSignatureValidated = httpSignature.verifySignature( + let httpSignatureValidated = httpSignature.verifySignature( signature, authUser.key.keyPem, ); + // If signature validation failed, try refetching the actor + if (!httpSignatureValidated) { + authUser.key = await dbResolver.refetchPublicKeyForApId(authUser.user); + + if (authUser.key == null) { + return "skip: failed to re-resolve user publicKey"; + } + + httpSignatureValidated = httpSignature.verifySignature( + signature, + authUser.key.keyPem, + ); + } + // また、signatureのsignerは、activity.actorと一致する必要がある if (!httpSignatureValidated || authUser.user.uri !== activity.actor) { // 一致しなくても、でもLD-Signatureがありそうならそっちも見る diff --git a/packages/backend/src/remote/activitypub/check-fetch.ts b/packages/backend/src/remote/activitypub/check-fetch.ts index e7d011d90..b583a4d7e 100644 --- a/packages/backend/src/remote/activitypub/check-fetch.ts +++ b/packages/backend/src/remote/activitypub/check-fetch.ts @@ -87,11 +87,25 @@ export async function checkFetch(req: IncomingMessage): Promise { } // HTTP-Signatureの検証 - const httpSignatureValidated = httpSignature.verifySignature( + let httpSignatureValidated = httpSignature.verifySignature( signature, authUser.key.keyPem, ); + // If signature validation failed, try refetching the actor + if (!httpSignatureValidated) { + authUser.key = await dbResolver.refetchPublicKeyForApId(authUser.user); + + if (authUser.key == null) { + return 403; + } + + httpSignatureValidated = httpSignature.verifySignature( + signature, + authUser.key.keyPem, + ); + } + if (!httpSignatureValidated) { return 403; } diff --git a/packages/backend/src/remote/activitypub/db-resolver.ts b/packages/backend/src/remote/activitypub/db-resolver.ts index 52626f399..d8aa3b706 100644 --- a/packages/backend/src/remote/activitypub/db-resolver.ts +++ b/packages/backend/src/remote/activitypub/db-resolver.ts @@ -17,7 +17,7 @@ import { Cache } from "@/misc/cache.js"; import { uriPersonCache, userByIdCache } from "@/services/user-cache.js"; import type { IObject } from "./type.js"; import { getApId } from "./type.js"; -import { resolvePerson } from "./models/person.js"; +import { resolvePerson, updatePerson } from "./models/person.js"; import {redisClient, subscriber} from "@/db/redis.js"; const publicKeyCache = new Cache("publicKey", 60 * 30); @@ -152,7 +152,7 @@ export default class DbResolver { */ public async getAuthUserFromKeyId(keyId: string): Promise<{ user: CacheableRemoteUser; - key: UserPublickey; + key: UserPublickey | null; } | null> { const key = await publicKeyCache.fetch( keyId, @@ -204,6 +204,15 @@ export default class DbResolver { key, }; } + + public async refetchPublicKeyForApId(user: CacheableRemoteUser): Promise { + await updatePerson(user.uri!, undefined, undefined, user); + let key = await UserPublickeys.findOneBy({ userId: user.id }); + if (key != null) { + await publicKeyByUserIdCache.set(user.id, key); + } + return key; + } } subscriber.on("message", async (_, data) => {