network/gaiia/tests/test_webhooks.py
2026-07-19 14:42:02 -05:00

62 lines
1.9 KiB
Python

import hashlib
import hmac
import time
import pytest
from gaiia import WebhookSignatureError, verify_webhook_signature
def _make_header(secret: str, timestamp: int, body: bytes) -> str:
sig = hmac.new(
secret.encode(), f"{timestamp}.{body.decode()}".encode(), hashlib.sha256
).hexdigest()
return f"t={timestamp},v1={sig}"
def test_valid_signature_passes():
secret = "whsec_test"
body = b'{"hello":"world"}'
ts = int(time.time())
header = _make_header(secret, ts, body)
verify_webhook_signature(header_value=header, raw_body=body, secret=secret)
def test_tampered_body_fails():
secret = "whsec_test"
body = b'{"hello":"world"}'
ts = int(time.time())
header = _make_header(secret, ts, body)
with pytest.raises(WebhookSignatureError):
verify_webhook_signature(
header_value=header, raw_body=b'{"hello":"WORLD"}', secret=secret
)
def test_old_timestamp_rejected():
secret = "whsec_test"
body = b'{"x":1}'
ts = int(time.time()) - 3600
header = _make_header(secret, ts, body)
with pytest.raises(WebhookSignatureError):
verify_webhook_signature(
header_value=header, raw_body=body, secret=secret, tolerance_seconds=60
)
def test_multiple_signatures_one_match():
secret = "whsec_test"
body = b"abc"
ts = int(time.time())
real = _make_header(secret, ts, body).split("v1=")[1]
header = f"t={ts},v1=ffffffff,v1={real}"
verify_webhook_signature(header_value=header, raw_body=body, secret=secret)
def test_missing_components():
with pytest.raises(WebhookSignatureError):
verify_webhook_signature(header_value="", raw_body=b"", secret="x")
with pytest.raises(WebhookSignatureError):
verify_webhook_signature(header_value="v1=abc", raw_body=b"", secret="x")
with pytest.raises(WebhookSignatureError):
verify_webhook_signature(header_value="t=123", raw_body=b"", secret="x")