Verify Webhook Signatures from Stairoids Using HMAC
Validate the X-Stairoids-Signature header on every incoming webhook using HMAC-SHA256 to confirm payloads are authentic and have not been tampered with.
Stairoids signs every webhook delivery with an HMAC-SHA256 signature so you can verify that the payload was genuinely sent by Stairoids and has not been tampered with in transit. Verifying signatures is strongly recommended for any production endpoint — without it, your webhook handler has no way to distinguish a legitimate Stairoids delivery from a spoofed or replayed request.
Always use a constant-time comparison function when comparing signatures — timingSafeEqual in Node.js, hmac.compare_digest in Python, hash_equals in PHP. Standard string equality (===, ==) is vulnerable to timing attacks that can allow an attacker to forge a valid signature byte by byte.
When Stairoids delivers a webhook, it includes an X-Stairoids-Signature header formatted as:
X-Stairoids-Signature: sha256=<hex-digest>
The hex digest is computed by running HMAC-SHA256 over the raw request body bytes using your webhook secret as the key. To verify the signature in your handler:
1
Extract the signature header
Read the X-Stairoids-Signature header from the incoming request.
2
Get the raw request body
Capture the raw bytes of the request body before any JSON parsing. Parsing and re-serialising the JSON may alter whitespace or key ordering and will produce a different digest.
3
Compute the expected signature
Compute HMAC-SHA256(raw_body, webhook_secret) and prepend sha256= to the hex-encoded result.
4
Compare using constant-time equality
Compare your computed signature against the header value using a timing-safe comparison function. If they match, the payload is authentic.
Use the raw request body bytes — do not parse and re-serialize the JSON before hashing. Even a single whitespace difference between the original bytes and your re-serialised string will cause verification to fail.
Your webhook secret is unique to each registered endpoint. To find it:
Open the Stairoids dashboard and navigate to Settings → Webhooks.
Click on the endpoint whose secret you need.
Click Reveal secret to display the value.
Copy the secret and store it as an environment variable in your application — never hardcode it in source code.
Your webhook secret grants the ability to forge valid signatures. Treat it like a password: store it in a secrets manager or environment variable, never commit it to source control, and rotate it immediately if you suspect it has been compromised.
If you need to rotate the secret — for example, after a suspected exposure — follow these steps to avoid dropping events during the transition:
1
Generate a new secret
In the Stairoids dashboard, go to Settings → Webhooks, click your endpoint, and click Rotate secret. Stairoids will generate a new secret and briefly accept signatures from both the old and new secret during a 15-minute overlap window.
2
Update your application
Deploy the new secret as an environment variable in your webhook handler. Verify that your application is using the new secret and that verification is passing on incoming deliveries.
3
Revoke the old secret
Return to Settings → Webhooks, click your endpoint, and click Confirm rotation to immediately invalidate the old secret. Deliveries signed with the old secret will now fail verification.
During the rotation overlap window you can run both old and new secrets in parallel in your verification code — try the new secret first, and fall back to the old secret — to achieve a zero-downtime rotation.