Skip to main content

Signature Verification

Every webhook delivery is signed with your webhook's signing_secret using HMAC-SHA256. This lets you verify the payload was sent by OlaClick and hasn't been tampered with.

How it works​

OlaClick computes an HMAC-SHA256 hash of the raw request body using your signing_secret and sends it in the X-OlaClick-Signature header:

X-OlaClick-Signature: sha256=<hex-encoded-hmac>

To verify:

  1. Read the X-OlaClick-Signature header from the request
  2. Compute HMAC-SHA256 of the raw body using your signing_secret
  3. Compare using a timing-safe function

Where to get the signing secret​

The signing_secret is set when a webhook configuration is created. For connectors, OlaClick uses the connector's OAuth client_id as the signing secret (set automatically during the connection setup). For API-created webhooks, you provide it via Create Webhook.

Implementation​

const crypto = require('crypto');

function verifySignature(rawBody, signatureHeader, signingSecret) {
if (typeof signatureHeader !== 'string') return false;

const expected = Buffer.from(
'sha256=' + crypto
.createHmac('sha256', signingSecret)
.update(rawBody)
.digest('hex'),
);
const received = Buffer.from(signatureHeader);

return (
expected.length === received.length &&
crypto.timingSafeEqual(expected, received)
);
}

// In your handler:
app.post('/webhooks/olaclick', (req, res) => {
const isValid = verifySignature(
req.rawBody, // raw string, NOT parsed JSON
req.headers['x-olaclick-signature'],
process.env.WEBHOOK_SIGNING_SECRET,
);

if (!isValid) {
return res.status(401).json({ error: 'invalid_signature' });
}

// Process event...
res.status(200).json({ status: 'received' });
});

Important​

  • Always use the raw request body string — not a re-serialized version of the parsed JSON. Re-serializing can change key order or whitespace, breaking the signature.
  • Always use a timing-safe comparison (timingSafeEqual, compare_digest, hash_equals, secure_compare) to prevent timing attacks.
  • Reject requests with missing or invalid signatures — never process an unverified payload.