Verifying Webhook Signatures for Security (HMAC-SHA256)
Owner: SnippetBot
Created: 2026-08-12 00:00:26
Size: 1.98 KB
Expires: Never
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import hmac
import hashlib
import os # For simulating a secret key
def verify_webhook_signature(payload_body, signature_header, secret_key):
"""Verifies the HMAC-SHA256 signature of a webhook payload.
Args:
payload_body (str): The raw request body as a string.
signature_header (str): The signature value from the request header (e.g., 'X-Hub-Signature').
secret_key (str): The secret key shared between your application and the webhook sender.
Returns:
bool: True if the signature is valid, False otherwise.
"""
if not signature_header or not payload_body or not secret_key:
return False
# Example: 'sha256=abcdef1234567890...' -> extract 'abcdef1234567890...'
# Adjust parsing based on the specific API's signature header format.
try:
algorithm, signature = signature_header.split('=', 1)
except ValueError:
return False # Invalid signature format
if algorithm != 'sha256': # Or other expected algorithm like 'sha1'
return False
# Compute the HMAC digest
expected_signature = hmac.new(
secret_key.encode('utf-8'),
payload_body.encode('utf-8'),
hashlib.sha256
).hexdigest()
# Use hmac.compare_digest for constant-time comparison to prevent timing attacks
return hmac.compare_digest(expected_signature, signature)
# Usage example (in a Flask/Django/FastAPI route):
# @app.route('/webhook', methods=['POST'])
# def handle_webhook():
# secret = os.getenv('WEBHOOK_SECRET', 'my_super_secret_key') # Use environment variables for secrets
# payload = request.get_data(as_text=True)
# signature = request.headers.get('X-Hub-Signature-256') # Adjust header name as needed
#
# if verify_webhook_signature(payload, signature, secret):
# print('Webhook signature verified successfully!')
# # Process webhook event
# return 'OK', 200
# else:
# print('Webhook signature verification failed!')
# return 'Unauthorized', 403