Webhook Signatures

All webhooks are signed using HMAC-SHA256. You should always verify the signature before processing a webhook.

Signature Header

The signature is included in the X-Bedrock-Signature header:

X-Bedrock-Signature: sha256=a1b2c3d4e5f6...

Verification Process

  1. Get the raw request body (as a string)

  2. Get the signature from the header

  3. Compute HMAC-SHA256 of the body using your webhook secret

  4. Compare your computed signature with the header value

Code Examples

Node.js

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payload, 'utf8')
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// Express middleware
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-bedrock-signature'];
  const payload = req.body.toString();

  if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(payload);
  // Process the event...

  res.status(200).send('OK');
});

Python

Go

PHP

Security Tips

  1. Use timing-safe comparison - Always use constant-time comparison functions to prevent timing attacks

  2. Keep your secret secure - Store the webhook secret in environment variables

  3. Validate the payload - After verifying the signature, validate the event data

  4. Use HTTPS - Webhook endpoints should always use HTTPS

  5. Reject old timestamps - Optionally check X-Bedrock-Timestamp to reject old webhooks

Last updated