fix: Refetch user keys when HTTP Signature validation fails
Co-authored-by: Erin Shepherd <erin.shepherd@e43.eu>
This commit is contained in:
parent
bdf3311402
commit
c4ec2d0942
3 changed files with 42 additions and 4 deletions
|
@ -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がありそうならそっちも見る
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue