Verifying Webhook Signatures

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:

  1. Retrieve the rivo-signature from the webhook request headers.
  2. Calculate the HMAC-SHA256 hash of the raw request body using your webhook’s secret token as the key.
  3. Encode the resulting hash in Base64.
  4. Compare the Base64-encoded hash with the received rivo-signature using a timing-safe comparison.
  5. 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 === with crypto.timingSafeEqual() to prevent timing attacks.