Praetorian
Praetorian

Reputation: 119

How can I validate payloads from GitHub webhooks in Python 3?

I've realized auto-deploying of my Flask app on the server by Github webhooks, but I cannot adapt Ruby script specified in the manual to Python 3 to validate the POST-request. I've tried this:

from flask import Flask, request
from hmac import HMAC, compare_digest
from hashlib import sha1

app = Flask(__name__)

def verify_signature(req):
     received_sign = req.headers.get('X-Hub-Signature').split('sha1=')[-1].strip()
     secret = 'my_secret_string'.encode()
     expected_sign = HMAC(key=secret, msg=req.data, digestmod=sha1).hexdigest()
     return compare_digest(received_sign, expected_sign)

@app.route('/webhook', methods=['POST', 'GET'])
def webhook():
    if request.method == 'POST':
        if verify_signature(request):
            do_smth()
            return 'Successfully', 200
        return 'Forbidden', 403
    return 'Not allowed', 405

Also I tried other variants with sha1(...).hexdigest() and compare_digest() from secrets package, but received signature always differs.

What do I do wrong?

Upvotes: 5

Views: 2223

Answers (2)

do-me
do-me

Reputation: 2188

Use SHA-256 instead of SHA-1

Instead of SHA-1 GitHub recommends using the more secure SHA-256.

Changed your code respectively for convenience.

from flask import Flask, request
from hmac import HMAC, compare_digest
from hashlib import sha256

app = Flask(__name__)

def verify_signature(req):
     received_sign = req.headers.get('X-Hub-Signature-256').split('sha256=')[-1].strip()
     secret = 'my_secret_string'.encode()
     expected_sign = HMAC(key=secret, msg=req.data, digestmod=sha256).hexdigest()
     return compare_digest(received_sign, expected_sign)

@app.route('/webhook', methods=['POST', 'GET'])
def webhook():
    if request.method == 'POST':
        if verify_signature(request):
            do_smth()
            return 'Successfully', 200
        return 'Forbidden', 403
    return 'Not allowed', 405

Upvotes: 3

Praetorian
Praetorian

Reputation: 119

I've updated the code. Now it works well.

Upvotes: 2

Related Questions