Files
oneuptime/Common/Server/Middleware/WhatsAppAuthorization.ts

88 lines
2.5 KiB
TypeScript

import {
ExpressResponse,
NextFunction,
OneUptimeRequest,
} from "../Utils/Express";
import Response from "../Utils/Response";
import BadDataException from "../../Types/Exception/BadDataException";
import GlobalConfig from "../../Models/DatabaseModels/GlobalConfig";
import GlobalConfigService from "../Services/GlobalConfigService";
import ObjectID from "../../Types/ObjectID";
import crypto from "crypto";
import logger from "../Utils/Logger";
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
export default class WhatsAppAuthorization {
@CaptureSpan()
public static async isAuthorizedWhatsAppRequest(
req: OneUptimeRequest,
res: ExpressResponse,
next: NextFunction,
): Promise<void> {
logger.debug("Starting WhatsApp webhook signature verification");
const signature: string | undefined = req.headers["x-hub-signature-256"] as
| string
| undefined;
if (!signature) {
logger.error(
"WhatsApp webhook request missing X-Hub-Signature-256 header.",
);
return Response.sendErrorResponse(
req,
res,
new BadDataException("Missing X-Hub-Signature-256 header."),
);
}
const globalConfig: GlobalConfig | null =
await GlobalConfigService.findOneBy({
query: {
_id: ObjectID.getZeroObjectID().toString(),
},
props: {
isRoot: true,
},
select: {
metaWhatsAppAppSecret: true,
},
});
const appSecret: string | undefined =
globalConfig?.metaWhatsAppAppSecret?.trim() || undefined;
if (!appSecret) {
logger.error(
"Meta WhatsApp App Secret is not configured. Cannot verify webhook signature.",
);
return Response.sendErrorResponse(
req,
res,
new BadDataException("Meta WhatsApp App Secret is not configured."),
);
}
const rawBody: string = req.rawBody || "";
const expectedSignature: string = `sha256=${crypto.createHmac("sha256", appSecret).update(rawBody).digest("hex")}`;
if (
!crypto.timingSafeEqual(
Buffer.from(expectedSignature) as Uint8Array,
Buffer.from(signature) as Uint8Array,
)
) {
logger.error("WhatsApp webhook signature verification failed.");
return Response.sendErrorResponse(
req,
res,
new BadDataException("WhatsApp webhook signature verification failed."),
);
}
logger.debug("WhatsApp webhook signature verified successfully");
next();
}
}