I created a URL in Pipedream to forward webhook requests to, which then forwards the body to Power Automate. In Pipedream the validation shows as successful returning the response Zoom needs, but Zoom validation is still failing. Anyone know what is wrong with my code?
[ Suspicious Content] import axios from “axios”;
import crypto from “crypto”;
export default defineComponent({
async run({ event }) {
const ZOOM_WEBHOOK_SECRET_TOKEN = process.env.ZOOM_WEBHOOK_SECRET_TOKEN;
const POWER_AUTOMATE_URL = process.env.POWER_AUTOMATE_URL;
if (!ZOOM_WEBHOOK_SECRET_TOKEN || !POWER_AUTOMATE_URL) {
return {
status: 500,
body: "Missing environment variables"
};
}
const headers = {};
for (const [key, value] of Object.entries(event.headers || {})) {
headers[key.toLowerCase()] = value;
}
const timestamp = headers["x-zm-request-timestamp"];
const signature = headers["x-zm-signature"];
if (!timestamp || !signature) {
return {
status: 400,
body: "Missing required Zoom headers"
};
}
const body = event.body;
// For signature validation
const rawBodyString = JSON.stringify(body);
const message = `v0:${timestamp}:${rawBodyString}`;
const computedHash = crypto
.createHmac("sha256", ZOOM_WEBHOOK_SECRET_TOKEN)
.update(message)
.digest("hex");
const expectedSignature = `v0=${computedHash}`;
if (signature !== expectedSignature) {
return {
status: 401,
headers: { "Content-Type": "application/json" },
body: { message: "Unauthorized request to Zoom Webhook." }
};
}
// ✅ Immediate return for endpoint validation
if (body.event === "endpoint.url_validation") {
const plainToken = body?.payload?.plainToken;
const encryptedToken = crypto
.createHmac("sha256", ZOOM_WEBHOOK_SECRET_TOKEN)
.update(plainToken)
.digest("hex");
return {
status: 200,
headers: { "Content-Type": "application/json" },
body: {
plainToken,
encryptedToken
}
};
}
// ✅ Forward valid events to Power Automate (after validation)
try {
await axios.post(POWER_AUTOMATE_URL, body, {
headers: { "Content-Type": "application/json" }
});
} catch (err) {
console.error("Error forwarding to Power Automate:", err.message);
}
return {
status: 200,
headers: { "Content-Type": "application/json" },
body: { message: "Authorized request to Zoom Webhook." }
};
}
});