Verify Rivo webhook requests using HMAC-SHA256 and Base64 to ensure authenticity and prevent tampering.
Verifying Webhook Signatures
Each webhook request includes a rivo-signature
header containing a Base64-encoded HMAC-SHA256 hash of the raw payload. This allows you to confirm that the request is genuine and hasn’t been tampered with in transit.
🔐 Signature Verification Steps
To validate the webhook payload:
- Retrieve the
rivo-signature
from the webhook request headers. - Calculate the HMAC-SHA256 hash of the raw request body using your webhook’s secret token as the key.
- Encode the resulting hash in Base64.
- Compare the Base64-encoded hash with the received
rivo-signature
using a timing-safe comparison. - If the two match, the webhook is verified and can be safely processed.
You can find your webhook’s secret token by editing the webhook in the Rivo dashboard.
Example (JavaScript)
const rawPayload = '{"id":122573686,"points_amount":0,...}'; // Raw body string as received
const secretToken = 'your-secret-token'; // Replace with your actual webhook secret
const receivedSignature = 'Base64SignatureFromHeader'; // From 'rivo-signature' header
const crypto = require('crypto');
const hmac = crypto.createHmac('sha256', secretToken);
const expectedSignature = hmac.update(rawPayload).digest('base64');
const isValid = expectedSignature === receivedSignature;
Replace secretToken and rawPayload with your actual webhook secret and the raw request body.
Key Notes
- Encoding: The
rivo-signature
is Base64-encoded, so your calculated signature must use the same encoding. - Header: Signature is sent in the
rivo-signature
header. - Raw Payload: Always use the raw
event.body
string for signature calculation. Avoid parsing or re-stringifying the payload, as it may introduce discrepancies. - Timing-Safe Comparison: For production use, replace
===
withcrypto.timingSafeEqual()
to prevent timing attacks.