Signature verification
Learn how to verify Recurly webhook signatures to ensure notifications are authentic and untampered.
For all JSON‐formatted webhooks, Recurly includes a recurly-signature
header. Verifying this signature proves the notification came from Recurly and has not been altered. You can verify signatures manually or by using one of our client libraries.
Prerequisites and limitations
- Each webhook endpoint has a unique secret key (found on the Webhook Endpoints page).
- Signature verification only applies to JSON payloads (XML payloads are not signed).
- You must have access to the raw request body and the
recurly-signature
header.
Key details
Each webhook endpoint is assigned a unique secret key. The key can be found on the Webhook Endpoints page. The matching key will be needed for each endpoint you wish to verify.
Using a client library
Provide the recurly-signature
header, the secret key, and the raw request body:
begin
Recurly::Webhooks.verify_signature(header,
ENV['WEBHOOKS_KEY'],
request.body)
rescue Recurly::Errors::SignatureVerificationError => e
puts e.message
end
err := recurly.VerifyWebhookSignature(header, secret, body, recurly.DEFAULT_WEBHOOK_TOLERANCE)
if err != nil {
fmt.Errorf("Verify Webhook Signature failed with: %s", err.Error())
}
Manual check
The recurly-signature
header is formatted as a Unix timestamp (in milliseconds), followed by one or more hexadecimal signatures:
recurly-signature:1659641851,a8c8524a0cdd99e36b55d9fdf6c8aed2c2315dfa1a36c4961f65986ee6cf6ae9,cafe677a2e6fa177d1a73cd9a18e47533de4b8923bbe17e2e1be290717ca29c1
Signatures are generated via HMAC using SHA-256. When you regenerate a secret key, both the new and previous keys remain valid for 24 hours, resulting in multiple signatures in the header.
1. Extract timestamp and signature(s)
Split the header value on commas. The first element is the timestamp; the remaining elements are signature(s). Any other format is invalid.
2. Prepare the message
Concatenate:
- The timestamp
- A literal
.
character - The exact raw request body
3. Compute the expected signature
Compute the HMAC-SHA256 digest of the prepared message using your endpoint’s secret key.
4. Compare signatures
Use a constant-time comparison to check the expected signature against each signature from the header. The notification is valid if exactly one matches.
Also compare the timestamp against the current time. Some clock skew is normal, but a large discrepancy could indicate a replay attack.
Updated 23 days ago