Github apps: Securing webhooks with Python in Flask
Posted on Wed 15 January 2020 in github apps
Once you have your Github webhooks working you will want to add a bit of security to make sure that the requests are actually coming from Github. One way to do this is to verify the signature Github sends matches the digest of the message.
Here is an example of how this can be done:
@app.route("/git-providers/1/events/", methods=['POST'])
@csrf.exempt
def events():
# get the Github signature from the request header
header_signature = request.headers.get('X-Hub-Signature')
# pass request data and signature to verify function
verify_signature(request.get_data(), header_signature)
json = request.get_json()
return jsonify({'message': 'success'}), 200
def verify_signature(request_data, header_signature):
# do not store your secret key in your code, pull from environment variable
secret_key = os.environ.get('GITHUB_WEBHOOK_SECRET')
if not header_signature:
return jsonify({'message': 'failure'}), 404
# separate the signature from the sha1 indication
sha_name, signature = header_signature.split('=')
if sha_name != 'sha1':
return jsonify({'message': 'failure'}), 501
# create a new hmac with the secret key and the request data
mac = hmac.new(secret_key.encode(), msg=request_data, digestmod='sha1')
# verify the digest matches the signature
if not hmac.compare_digest(mac.hexdigest(), signature):
return jsonify({'message': 'failure'}), 404