Vatsal Arya
Vatsal Arya

Reputation: 21

Facebook webhook signature calculation failing

I am developing an application that uses Facebook Webhooks to receive payload from Facebook. For each call, Facebook provides a signature that I need to validate to ensure the payload's integrity and origin. I followed the steps and code in Facebook's documentation (https://developers.facebook.com/docs/messenger-platform/webhooks#validate-payloads), and am calculating the SHA-256 signature using the app secret. However, the signature this reference code generates does not match the one sent by Facebook in the x-hub-signature-256 header.

I am currently sending requests using either the Lead Ads Testing tool (https://developers.facebook.com/tools/lead-ads-testing) or the Test button on the webhook registration page. The signature generated by my code matches the one calculated by the tool https://www.devglan.com/online-tools/hmac-sha256-online. However, it does not match the signature sent by Facebook.

I have also followed the C# code given in (facebook webhook signature calculation (C#)) however this also generates the same signature as the Javascript or the tool but does not match the signature sent by Facebook.

This is the JavaScript code I am using: (This code is provided in the Facebook Documentation I mentioned earlier)

const express = require("express"),
bodyParser = require("body-parser"),
{ urlencoded, json } = require("body-parser"),
app = express();
const crypto = require("crypto");

app.use(bodyParser.json({
    verify: (req, res, buf) => {
        req.rawBody = buf
    }
}));

function verifyRequestSignature(req, res, buf) {
  var signature = req.headers["x-hub-signature-256"];
  if (!signature) {
    console.warn(`Couldn't find "x-hub-signature-256" in headers.`);
  } else {
    var elements = signature.split("=");
    var signatureHash = elements[1];
    var expectedHash = crypto
      .createHmac("sha256", "AppSecret")
      .update(buf)
      .digest("hex");
    console.log(expectedHash);
    
    if (signatureHash != expectedHash) {
      throw new Error("Couldn't validate the request signature.");
    }
  }
}

// Handle incoming requests
app.post("/webhook", (req, res) => {
  try {
    verifyRequestSignature(req, res, req.rawBody);
    // Handle the incoming webhook event here...
    res.status(200).send("EVENT_RECEIVED");
  } catch (err) {
    console.error(err);
    res.sendStatus(403);
  }
});

// Start the server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`);
});

Sample Data:

App-secret: 3f1e071f97065865829855e7b6e69dc8
Payload: {"entry":[{"id":"0","time":1683656757,"changes":[{"field":"leadgen","value":{"ad_id":"444444444","form_id":"444444444444","leadgen_id":"444444444444","created_time":1683656757,"page_id":"444444444444","adgroup_id":"44444444444"}}]}],"object":"page"}
Expected/Calculated signature: f5092edd80ab944fb1c66cf5d2f5534b100e16d18b117187635b55b2f4e6fc91
Signature Received: sha256=6f11c3490dbdf8e63af0287f40ccf159a12cac8e3f3213f09cc1d1247ceaa386

Can anyone help me figure out why the signature generated by my code does not match the one sent by Facebook?

Upvotes: 2

Views: 1191

Answers (1)

JeremyJAlpha
JeremyJAlpha

Reputation: 53

Be sure to compare it against this app secret in the business settings page and not the webhook verification token used in the initialize and challenge Get request / "route".

enter image description here

Also check out this other question: facebook webhook signature calculation (C#)

Upvotes: 3

Related Questions