Secure webhook URLs
Protect your webhook endpoint from unwanted or malicious traffic. Configure HTTPS to encrypt data transmitted between the sender and receiver. Here are the methods Ocrolus provides to strengthen security. All of these methods are opt-in.
- Webhook signature verification: Verify the authenticity of incoming requests using HMAC SHA256 signatures. Configure a unique secret per webhook endpoint.
- Allowlist of IP addresses: Restrict traffic to trusted sources by implementing ingress rules. Allow only requests originating from Ocrolus infrastructure.
- HTTP basic authentication: Add authentication credentials to your webhook URL. Grant Ocrolus access using basic auth in the registered endpoint.
Webhook signature verification
Verify the authenticity of incoming webhook requests using HMAC SHA256 signature verification. Configure a unique secret for each webhook endpoint to sign and verify payloads. Generate a secure random string between 16–128 characters and register it using the webhook secret management APIs.
Request headers
Each webhook request includes three headers for verification:
| Header | Description |
|---|---|
Webhook-Signature | HMAC SHA256 hex digest of the signed message |
Webhook-Timestamp | Unix timestamp (seconds) when the webhook was sent |
Webhook-Request-Id | Unique identifier for the webhook request |
Signature construction
The signature is computed over a message with the following format. All fields are bytes.
{timestamp}.{request_id}.{body}
| Component | Source |
|---|---|
timestamp | Value from Webhook-Timestamp header |
request_id | Value from Webhook-Request-Id header |
body | Raw request body |
Verifying webhooks
import hmac
import hashlib
from flask import request
WEBHOOK_SECRET = b"your_webhook_secret" # get from environment
def verify_webhook_signature(request) -> bool:
signature = request.headers.get("Webhook-Signature")
timestamp = request.headers.get("Webhook-Timestamp")
request_id = request.headers.get("Webhook-Request-Id")
body = request.get_data()
signed_message = f"{timestamp}.{request_id}.".encode() + body
expected_signature = hmac.new(
WEBHOOK_SECRET,
signed_message,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected_signature, signature)
Webhook secret management APIs
Secret rotation
Rotate your webhook secret without downtime by following these steps:
- Generate a new secret: Create a new secret (16–128 characters) using a secure random generator.
- Update your verification logic: Modify your webhook handler to validate signatures against both the current and new secret.
- Update the secret via API: Call the appropriate API endpoint to register your new secret.
- Remove the old secret: Remove the old secret from your verification logic once webhooks arrive with signatures from the new secret.
Allowlist of IP addresses
To ensure the security of your webhook, we advise implementing ingress rules that restrict unfamiliar traffic. By blocking all traffic that does not originate from Ocrolus or your trusted infrastructure, you can prevent unauthorized access to your webhook endpoint.
For your reference, the notifications from your registered webhooks will be sent from the allowed IP addresses. To learn more about allowed IP addresses, see IP address allowlist.
HTTP basic authentication scheme
Use Basic Authentication to secure your webhook endpoint. Include the webhook credentials in the registered URL to grant Ocrolus access, such as https://webhook_user:[email protected]/the/rest/of/the/url.
curl -X POST \
-H "Content-Type: application/json" \
-d '{"event" : "BOOK_VERIFIED"}' \
https://webhook_user:[email protected]/the/rest/of/the/url
Updated 2 days ago