What is a webhook authentication?
Webhook authentication is the mechanism — usually HMAC signatures — that proves an inbound webhook came from the claimed source. Most modern providers (Stripe, GitHub, Shopify, Slack) sign the raw body with a shared secret. Variants exist: Twilio signs the URL plus form parameters instead of the body; legacy systems sometimes use Basic auth or IP allowlisting. Treat any unsigned webhook as untrusted input — "the URL is hard to guess" is not authentication. The first thing your handler does (after reading raw body) must be verifying the signature, failing closed on any error including missing header, returning 401 not 400 or 500.
Authentication answers: "is this request really from who it claims to be from?" For webhooks, the answer is almost always HMAC signatures. A handful of providers use other mechanisms; understanding the landscape helps you handle integrations that aren't Stripe-shaped.
The mechanisms in actual use:
- HMAC signatures over the raw body (Stripe, GitHub, Shopify, Slack, most modern providers). Source signs body with a shared secret; receiver recomputes and compares. Standard. See webhook-signature and signature-verification.
- HMAC over URL + form params (Twilio). Twilio constructs a signature input from the full URL and sorted form parameters, signs that with the auth token. Different from body-signing — must follow Twilio's exact spec.
- Basic auth (rare, legacy). Source includes Authorization: Basic header with credentials you provided when registering. Equivalent to a per-receiver password. Mostly seen in older integrations and self-hosted webhook senders.
- OAuth 2.0 bearer tokens (rare for webhooks). Source includes a short-lived token in Authorization: Bearer. Adds complexity (token refresh) for marginal security gain over HMAC. Almost never the right choice.
- Mutual TLS (very rare in public webhooks; common in B2B partner integrations). Source presents a client certificate; receiver verifies against a trusted CA. Strong authentication, high operational cost.
- IP allowlisting (defense-in-depth, never sole defense). Provider publishes a range of source IPs; receiver firewall blocks anything else. Useful as a layer but insufficient alone — IPs change, attackers can spoof in some network topologies, and it gives no message integrity.
- Nothing (alarmingly common). Some legacy or first-draft webhook integrations rely on "the URL is hard to guess" as authentication. This is not authentication. Treat any unsigned webhook as untrusted input — if your handler runs business logic on unsigned webhooks, it's a public RPC anyone can call.
What good authentication looks like in your handler: the first thing the handler does (after reading raw body) is verify, the verification fails closed (rejects on any error including missing header), failures return 401 not 400 or 500, and the success path is gated behind verification — there is no code path that processes the body before the signature is checked.
Authentication is necessary but not sufficient. A signed webhook can still be replayed (see replay-attack), can still be a duplicate (see idempotency), can still be malformed (validate the parsed payload separately). Auth is the first gate, not the only gate.
See Webhook Authentication in real traffic
WebhookWhisper captures every webhook with full headers, body, signature, and timing — so concepts like webhook authentication stop being abstract and become something you can inspect.
Start Free