fix: Refetch user keys when HTTP Signature validation fails

Co-authored-by: Erin Shepherd <erin.shepherd@e43.eu>
This commit is contained in:
Erin Shepherd 2023-10-17 01:27:26 +00:00 committed by Kainoa Kanter
parent bdf3311402
commit c4ec2d0942
3 changed files with 42 additions and 4 deletions

View file

@ -95,11 +95,25 @@ export default async (job: Bull.Job<InboxJobData>): Promise<string> => {
}
// 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がありそうならそっちも見る

View file

@ -86,11 +86,25 @@ export async function checkFetch(req: IncomingMessage): Promise<number> {
}
// 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;
}

View file

@ -17,7 +17,8 @@ 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";
const publicKeyCache = new Cache<UserPublickey | null>("publicKey", 60 * 30);
const publicKeyByUserIdCache = new Cache<UserPublickey | null>(
@ -151,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,
@ -203,4 +204,13 @@ export default class DbResolver {
key,
};
}
public async refetchPublicKeyForApId(user: CacheableRemoteUser): Promise<UserPublickey | null> {
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;
}
}