mirror of
https://github.com/outline/outline.git
synced 2026-06-13 03:14:59 +03:00
cad670f19c
Co-authored-by: Tom Moor <tom@getoutline.com> closes #6795
50 lines
1.2 KiB
TypeScript
50 lines
1.2 KiB
TypeScript
import crypto from "node:crypto";
|
|
import type { Next } from "koa";
|
|
import type { APIContext } from "@server/types";
|
|
import { safeEqual } from "@server/utils/crypto";
|
|
|
|
export default function validateWebhook({
|
|
secretKey,
|
|
getSignatureFromHeader,
|
|
hmacSign = true,
|
|
}: {
|
|
secretKey: string | ((ctx: APIContext) => Promise<string | undefined>);
|
|
getSignatureFromHeader: (ctx: APIContext) => string | undefined;
|
|
hmacSign?: boolean;
|
|
}) {
|
|
return async function validateWebhookMiddleware(ctx: APIContext, next: Next) {
|
|
const { body } = ctx.request;
|
|
const signatureFromHeader = getSignatureFromHeader(ctx);
|
|
|
|
if (!signatureFromHeader) {
|
|
ctx.status = 401;
|
|
ctx.body = "Missing signature header";
|
|
return;
|
|
}
|
|
|
|
const key =
|
|
typeof secretKey === "function" ? await secretKey(ctx) : secretKey;
|
|
|
|
if (!key) {
|
|
ctx.status = 401;
|
|
ctx.body = "Invalid signature";
|
|
return;
|
|
}
|
|
|
|
const computedSignature = hmacSign
|
|
? crypto
|
|
.createHmac("sha256", key)
|
|
.update(JSON.stringify(body))
|
|
.digest("hex")
|
|
: key;
|
|
|
|
if (!safeEqual(computedSignature, signatureFromHeader)) {
|
|
ctx.status = 401;
|
|
ctx.body = "Invalid signature";
|
|
return;
|
|
}
|
|
|
|
return next();
|
|
};
|
|
}
|