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:

HeaderDescription
Webhook-SignatureHMAC SHA256 hex digest of the signed message
Webhook-TimestampUnix timestamp (seconds) when the webhook was sent
Webhook-Request-IdUnique 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}
ComponentSource
timestampValue from Webhook-Timestamp header
request_idValue from Webhook-Request-Id header
bodyRaw 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:

  1. Generate a new secret: Create a new secret (16–128 characters) using a secure random generator.
  2. Update your verification logic: Modify your webhook handler to validate signatures against both the current and new secret.
  3. Update the secret via API: Call the appropriate API endpoint to register your new secret.
  4. 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