-1

I can't manage to validate the X-Hub-Signature-256 for my meta / whatsapp webhook in flask successfully.

Can anyone tell me where the error is or provide me with a working example?

import base64
import hashlib
import hmac
import os

from dotenv import load_dotenv
from flask import Flask, jsonify, request
from werkzeug.middleware.proxy_fix import ProxyFix

load_dotenv()

API_SECRET = os.environ.get('API_SECRET')

app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_host=1)


def verify_webhook(data, hmac_header):

    hmac_recieved = str(hmac_header).removeprefix('sha256=')
    digest = hmac.new(API_SECRET.encode('utf-8'), data,
                      digestmod=hashlib.sha256).digest()
    computed_hmac = base64.b64encode(digest)

    return hmac.compare_digest(computed_hmac, hmac_recieved.encode('utf-8'))


@app.route("/whatsapp", methods=["GET", "POST"])
def whatsapp_webhook():


    if request.method == "POST":

        try:
            data = request.get_data()

            if not verify_webhook(data, request.headers.get('X-Hub-Signature-256')):
                return "", 401

        except Exception as e:
            print(e)
            return "", 500

    return jsonify({"status": "success"}, 200)
TylerH
  • 20,799
  • 66
  • 75
  • 101
Gurkenkönig
  • 678
  • 15
  • 36

3 Answers3

1

This seems to work:

def verify_webhook(data, hmac_header):
  hmac_recieved = str(hmac_header).removeprefix('sha256=')
  digest = hmac.new(API_SECRET.encode('utf-8'), data.encode('utf-8'), hashlib.sha256).hexdigest()
  return hmac.compare_digest(hmac_recieved, digest)

If you run this test:

import base64
import hashlib
import hmac
import os

API_SECRET = 'very_secret_key'

def verify_webhook(data, hmac_header):
  hmac_recieved = str(hmac_header).removeprefix('sha256=')
  digest = hmac.new(API_SECRET.encode('utf-8'), data.encode('utf-8'), hashlib.sha256).hexdigest()
  return hmac.compare_digest(hmac_recieved, digest)

print(verify_webhook('Good morning', 'sha256=63e447ebe2bb46cb621972656087950c9d3a437caa61ece01f18094cc99f5a16'))

It returns True as expected:

$ python3 xhub_new.py
True
Unai
  • 181
  • 1
  • 11
0

make sure you are using the correct "API_SECRET". I was confusing it trying to sign the request with the token that validates the webhook, but it is the "secret key" of the meta app.

Roberto
  • 105
  • 4
0

For those who are curious about locating the elusive "API_SECRET," you can conveniently find it within your facebook application settings:

Facebook Developer Dashboard