Home|Blog List

Verifying payloads from GitHub webhooks in Flask

Thursday, January 28, 2016 • Estimated Reading Time: 2 minutes

When receiving payload from GitHub webhooks it's a good idea to validate them before taking any action. This assures that your application does not accept payloads other than those sent by GitHub. Whitelisting GitHub's IP addresses is one option but validating a secret token that is configured in a GitHub webhook is much easier.

The GitHub documentation provides a nice example of how this is done in Ruby. In Python's Flask, the code is very similar:

import hashlib
import hmac

def verify_hash(request_body, header_value):
    h = hmac.new(os.getenv("SECRET_TOKEN", ""), request_body, hashlib.sha256)
    return hmac.compare_digest("sha256=" + h.hexdigest(), header_value)

@app.route("/regenerate-documentation", methods=["POST"])
def regenerate_docs():
    header_value = request.headers.get("X-Hub-Signature")
    request_body = request.get_data()

    if verify_hash(request_body, header_value):
        print("Success!")
    else:
        return abort(500)

In this example, the secret token is defined in the SECRET_TOKEN environment variable. The request coming from GitHub will contain the secret token in the X-Hub-Signature header, along with a ton of other useful data. Now all that's left is to compute the hash with Python's hmac module:

hmac.new(key, msg=None, digestmod=None)

If the hashes match, the request is valid and your application can trigger whatever action it is configured to do.