Skip to main content
Every webhook request from Fanfare includes a cryptographic signature that allows you to verify the request’s authenticity. Always verify signatures before processing webhook events.

Signature Overview

Fanfare uses HMAC-SHA256 to sign webhook payloads. The signature is computed from:
  1. The timestamp of the request
  2. The raw request body
  3. Your webhook signing secret

Signature Headers

Each webhook request includes these headers:

Verification Process

Step 1: Extract Headers

Step 2: Prepare the Signed Payload

Concatenate the timestamp and the raw request body with a period:

Step 3: Compute Expected Signature

Step 4: Compare Signatures

Prevent replay attacks by rejecting old webhooks:

Complete Verification Example

Node.js / Express

Next.js API Route

Python / Flask

Webhook Secrets

Obtaining Your Secret

Your webhook signing secret is provided when you create a webhook endpoint:
  1. Go to Settings > Webhooks in your dashboard
  2. Create or edit an endpoint
  3. Copy the signing secret (begins with whsec_)

Rotating Secrets

To rotate your webhook secret:
  1. Generate a new secret in the dashboard
  2. Update your server to accept both old and new secrets temporarily
  3. Verify webhooks are working with the new secret
  4. Remove the old secret from your server

Security Best Practices

1. Use Timing-Safe Comparison

Always use timing-safe comparison to prevent timing attacks:

2. Check Timestamp Age

Prevent replay attacks by rejecting old webhooks:

3. Store Secrets Securely

Never commit webhook secrets to version control. Use environment variables:

4. Use Raw Body

Parse the body as raw bytes before JSON parsing:

5. Log Failed Verifications

Monitor for signature failures which may indicate attacks:

Troubleshooting

Signature Mismatch

Common causes:
  1. Wrong secret: Ensure you’re using the correct webhook secret
  2. Body modification: Middleware may have modified the raw body
  3. Encoding issues: Ensure consistent UTF-8 encoding
  4. Header case sensitivity: Some frameworks lowercase headers

Timestamp Validation Failed

If timestamp validation fails:
  1. Check your server’s clock is synchronized (use NTP)
  2. Verify the timestamp header is being read correctly
  3. Consider increasing the max age temporarily for debugging

Testing Signature Verification

Generate a test signature to verify your implementation: