Webhook Security

Why Secure Your Webhooks?

Webhooks are a powerful way to receive real‑time data from external services. However, without proper security measures they can become a vector for attacks such as replay attacks, data tampering, and unauthorized data access.

Best Practices

  1. Use Secret Signatures – Require the sender to sign each payload with a shared secret (HMAC SHA‑256) and verify it on receipt.
  2. Validate Payload Structure – Use JSON schema validation to ensure only expected fields are processed.
  3. Enforce HTTPS – Always expose webhook endpoints over TLS to protect data in transit.
  4. Rate Limiting & IP Whitelisting – Limit calls per minute and restrict requests to known IP ranges when possible.
  5. Replay Protection – Include timestamps and nonces; reject messages older than a short window (e.g., 5 minutes).
  6. Minimal Permissions – Design the endpoint to only accept what it needs; avoid exposing extra data.

Sample Verification Code (Node.js)

const crypto = require('crypto');

function verifySignature(req, secret) {
    const signature = req.headers['x-signature'] || '';
    const payload = JSON.stringify(req.body);
    const hmac = crypto.createHmac('sha256', secret);
    const expected = 'sha256=' + hmac.update(payload).digest('hex');
    return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

// Express middleware
app.post('/webhook', express.json(), (req, res) => {
    const secret = process.env.WEBHOOK_SECRET;
    if (!verifySignature(req, secret)) {
        return res.status(401).send('Invalid signature');
    }
    // Process payload...
    res.status(200).send('OK');
});

Testing Your Endpoint

Use curl or a tool like Postman to simulate webhook calls. Ensure you include the required signature header.

curl -X POST https://example.com/webhook \
  -H "Content-Type: application/json" \
  -H "X-Signature: sha256=YOUR_SIGNATURE" \
  -d '{"event":"order.created","data":{"id":123}}'