Make authorized fetch configurable

This commit is contained in:
Jesse Wierzbinski 2023-10-15 20:07:39 -10:00
parent c0ff46559b
commit a8d8b70239
3 changed files with 48 additions and 27 deletions

View file

@ -101,6 +101,10 @@ force_sensitive = [] # NOT IMPLEMENTED
# Remove theses instances' media
remove_media = [] # NOT IMPLEMENTED
# Whether to verify HTTP signatures for every request (warning: can slow down your server
# significantly depending on processing power)
authorized_fetch = false
[filters]
# Drop notes with these regex filters (only applies to new activities)

View file

@ -57,34 +57,49 @@ export default async (
const body: APActivity = await req.json();
// Verify HTTP signature
const signature = req.headers.get("Signature") ?? "";
const signatureParams = signature
.split(",")
.reduce<Record<string, string>>((params, param) => {
const [key, value] = param.split("=");
params[key] = value.replace(/"/g, "");
return params;
}, {});
if (config.activitypub.authorized_fetch) {
// Check if date is older than 30 seconds
const date = new Date(req.headers.get("Date") ?? "");
const signedString = `(request-target): post /users/${username}/inbox\nhost: ${
config.http.base_url
}\ndate: ${req.headers.get("Date")}`;
const signatureBuffer = new TextEncoder().encode(signatureParams.signature);
const signatureBytes = new Uint8Array(signatureBuffer).buffer;
const publicKeyBuffer = (body.actor as any).publicKey.publicKeyPem;
const publicKey = await crypto.subtle.importKey(
"spki",
publicKeyBuffer,
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
false,
["verify"]
);
const verified = await crypto.subtle.verify(
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
publicKey,
signatureBytes,
new TextEncoder().encode(signedString)
);
if (date.getTime() < Date.now() - 30000) {
return errorResponse("Date is too old (max 30 seconds)", 401);
}
const signature = req.headers.get("Signature") ?? "";
const signatureParams = signature
.split(",")
.reduce<Record<string, string>>((params, param) => {
const [key, value] = param.split("=");
params[key] = value.replace(/"/g, "");
return params;
}, {});
const signedString = `(request-target): post /users/${username}/inbox\nhost: ${
config.http.base_url
}\ndate: ${req.headers.get("Date")}`;
const signatureBuffer = new TextEncoder().encode(
signatureParams.signature
);
const signatureBytes = new Uint8Array(signatureBuffer).buffer;
const publicKeyBuffer = (body.actor as any).publicKey.publicKeyPem;
const publicKey = await crypto.subtle.importKey(
"spki",
publicKeyBuffer,
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
false,
["verify"]
);
const verified = await crypto.subtle.verify(
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
publicKey,
signatureBytes,
new TextEncoder().encode(signedString)
);
if (!verified) {
return errorResponse("Invalid signature", 401);
}
}
// Get the object's ActivityPub type
const type = body.type;

View file

@ -55,6 +55,7 @@ export interface ConfigType {
force_sensitive: string[];
remove_media: string[];
fetch_all_colletion_members: boolean;
authorized_fetch: boolean;
};
filters: {
@ -184,6 +185,7 @@ export const configDefaults: ConfigType = {
discard_follows: [],
remove_media: [],
fetch_all_colletion_members: false,
authorized_fetch: false,
},
filters: {
note_filters: [],