import { hmacSha256Hex, timingSafeEqualStrings } from "../crypto"; /** * Accepts the signing schemes of the common forges: GitHub / Bitbucket (`X-Hub-Signature-256: sha256=`), * Gitea / Forgejo / Gogs (hex HMAC), GitLab (`X-Gitlab-Token` equal to the secret), and a bearer token or * `?secret=` for anything else. */ export async function verifyMirrorHook(secret: string, request: Request, body: string): Promise { const headers = request.headers; const hex = await hmacSha256Hex(secret, body); const prefixed = [headers.get("x-hub-signature-256"), headers.get("x-hub-signature")]; for (const header of prefixed) { if (header && timingSafeEqualStrings(`sha256=${hex}`, header.trim())) return true; } const plain = [headers.get("x-gitea-signature"), headers.get("x-forgejo-signature"), headers.get("x-gogs-signature")]; for (const header of plain) { if (header && timingSafeEqualStrings(hex, header.trim().toLowerCase())) return true; } const authorization = headers.get("authorization") ?? ""; const bearer = authorization.toLowerCase().startsWith("bearer ") ? authorization.slice("bearer ".length).trim() : null; const tokens = [headers.get("x-gitlab-token"), bearer, new URL(request.url).searchParams.get("secret")]; return tokens.some((token) => token !== null && token !== "" && timingSafeEqualStrings(secret, token)); }