HOW-TO

How to verify a webhook signature

Verify an incoming webhook with an HMAC signature so you only trust genuine events. Step-by-step with the security pitfalls to avoid.

Verifying a webhook signature ensures the event really came from the provider and was not forged or altered. The standard approach is an HMAC over the raw body with a shared secret — here is how to do it correctly.

Use the raw body

Compute the HMAC over the exact raw request body bytes, before any JSON parsing or re-serialization — even a whitespace change breaks the signature. Grab the raw body in your framework (many parse it by default) and pass it, plus your shared secret, into HMAC-SHA256.

Compare in constant time

Compare your computed signature to the header value using a constant-time comparison (like hmac.compare_digest or crypto.timingSafeEqual), never a plain ==, to avoid leaking match progress through timing. Reject the webhook if they differ, and consider checking a timestamp to prevent replay.

Step by step

1

Read the signature header the provider sends (e.g. X-Signature).

2

Compute HMAC-SHA256 over the RAW request body using your shared secret.

3

Compare your value to the header with a constant-time comparison.

4

Reject on mismatch; optionally verify a timestamp to block replays.

Try it now — free, no signup

Use the hash generator in your browser. Then, when you need it at scale with an API key and higher limits, grab the full Eveses API.

FAQ

Why does my signature never match?›
Almost always because you hashed the parsed/re-serialized body instead of the raw bytes. Use the exact raw payload.
Why not use == to compare?›
A normal comparison can leak how many characters matched via timing. Use a constant-time compare.

Related