# Security

## Signature Verification

Every webhook delivery includes a signature in the `X-Webhook-Signature` header. Verify this to ensure the request came from TokenBot.

### How It Works

1. TokenBot computes an HMAC-SHA256 of the raw request body using your webhook secret
2. The signature is sent as `X-Webhook-Signature: sha256=<hex_digest>`
3. You compute the same HMAC and compare

### Node.js Example

```javascript
const crypto = require('crypto');

function verifyWebhookSignature(body, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(body, 'utf8')
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express middleware
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  
  if (!verifyWebhookSignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  const event = JSON.parse(req.body);
  // Process event...
  
  res.status(200).send('OK');
});
```

### Python Example

```python
import hmac
import hashlib

def verify_signature(body: bytes, signature: str, secret: str) -> bool:
    expected = 'sha256=' + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)
```

## Best Practices

* Always verify signatures before processing events
* Use `crypto.timingSafeEqual` (Node.js) or `hmac.compare_digest` (Python) to prevent timing attacks
* Rotate your webhook secret periodically via `POST /webhooks/:id/rotate-secret`
* Respond with `2xx` quickly; process events asynchronously
