ARTICLE AD BOX
I'm building a webhook handler that needs to accept webhooks from multiple providers (Stripe, GitHub, Shopify, Twilio, etc.). Each provider uses different signature verification methods:
- Stripe: Uses `Stripe-Signature` header with format `t=timestamp,v1=signature` and HMAC-SHA256
- GitHub: Uses `X-Hub-Signature-256` header with format `sha256=hexdigest` and HMAC-SHA256
- Shopify: Uses `X-Shopify-Hmac-Sha256` header with base64-encoded HMAC-SHA256
- Twilio: Uses `X-Twilio-Signature` header with base64-encoded HMAC-SHA1, but requires the full URL in the signature calculation
- Slack: Uses `X-Slack-Signature` with format `v0=hash` and includes timestamp validation
The challenge is that each provider has:
- Different header names
- Different signature formats (hex, base64, prefixed strings)
- Different hash algorithms (SHA1, SHA256, SHA512)
- Different message formats (body only, timestamp + body, URL + body, etc.)
- Some require timestamp validation to prevent replay attacks
What I've tried:
I started with a simple switch statement, but it's becoming unmaintainable as I add more providers. I also need to ensure:
- Constant-time comparison to prevent timing attacks
- Proper timestamp validation where required
- Handling edge cases (missing headers, invalid formats)
Environment:
- Language: Go
- Framework: Gin (but solution should be framework-agnostic)
- Providers: Stripe, GitHub, Shopify, Twilio, Slack, and more
Expected behavior:
A clean, maintainable solution that can verify signatures from multiple providers with proper error handling and security best practices.
