Join our Newsletter — 33% off our NHI Course
Home› Guides› Webhook HMAC Signing vs mTLS vs IP Allowlisting:…
Guide Web & API Security

Webhook HMAC Signing vs mTLS vs IP Allowlisting: Choosing and Layering Sender Authentication by Threat

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 14 November 2026 17 min read
On this page

Most webhook receivers pick one sender check, usually whatever the provider documents first, and never ask which threat it actually stops. HMAC signing, mutual TLS and IP allowlisting answer different questions: HMAC proves a holder of a shared secret produced these exact bytes, mTLS proves a holder of a private key opened this connection, and an allowlist proves only that the packet came from an address range. Each fails in a different way when a secret leaks, a request is replayed or the provider's egress addresses are shared with thousands of other customers. This guide compares the three by threat, architecture and failure mode, with layering patterns, worked scenarios and a decision checklist, for application security engineers, platform teams and architects. Signature implementation detail lives in the Webhook Secrets Security Guide; this page is about choosing.

Key takeaways

  • Only message signatures bind identity to content. HMAC (or an asymmetric signature) covers the body and, in good schemes, a timestamp and message ID; mTLS and allowlisting authenticate the pipe, not the message.
  • IP allowlisting is not authentication. Provider egress ranges are shared by every customer of that provider, so an allowlist admits an attacker who registers their own account and points it at your URL. GitHub's own documentation does not recommend allowing by IP address.
  • mTLS moves the trust decision to your TLS terminator. It removes secrets from application code, but the check is only as good as how the terminator forwards the verified identity and whether anything behind it can be reached directly.
  • Replay is a property of the scheme, not the transport. Signed timestamps plus deduplication on a delivery ID stop replay; mTLS and allowlists do nothing against a request resent from a permitted source.
  • The webhook secret is a non-human credential. It needs an owner, a store, a rotation window and an exposure runbook, and the choice of mechanism decides how bad a leak is and how fast you can recover.

The short answer

Require message signing (HMAC, or an asymmetric scheme where the provider offers one) on every webhook route, with timestamp tolerance and deduplication. Add mTLS where the provider supports it and you already terminate client certificates, because it gives a second, independent factor that survives a leaked signing secret. Use IP allowlisting as noise reduction and as a firewall requirement for private networks, never as the control that decides whether an event is genuine. If a provider offers only an allowlist and no signature, treat every event as untrusted input and re-fetch the object from the provider API before acting on it.

A quick test for any design: assume an attacker has a free account with the same provider. Which check rejects their request to your endpoint? If the answer is "none", the design relies on the URL staying secret.

How each mechanism authenticates the sender

HMAC message signing

The provider and the receiver share a secret per endpoint. For each delivery the provider computes HMAC-SHA256 over a defined string, usually an ID, a timestamp and the raw body, and sends the result in a header. The receiver rebuilds the same string from the bytes it received, computes the HMAC with its copy of the secret and compares in constant time. The Standard Webhooks specification defines this as the v1 scheme with secrets of 24 to 64 random bytes, and an asymmetric v1a scheme using ed25519 in which the receiver holds only a public key. Verification happens in application code or a gateway, so it survives proxies that do not rewrite the body.

A close relative is a provider-signed bearer token. Google Cloud Pub/Sub push subscriptions send an OpenID Connect JWT in the Authorization header, signed by Google, and the receiver checks the signature, the aud claim and that the email claim matches the push service account. The token is not bound to the body and can be up to an hour old, so deduplication still matters.

Mutual TLS

The provider presents a client certificate during the TLS handshake and your terminator validates the chain and the identity in it. Slack documents this as an alternative to request signing: the terminator accepts client certificates under any DigiCert root, extracts the subject alternative name platform-tls-client.slack.com (or the common name), and injects it into a header such as X-Client-Certificate-SAN for the application to check. Slack requires that the application knows the terminator added the header, and rejects any other domain, including other slack.com subdomains. Verification is per connection, not per message, and it ends at the terminator: from there to the application the request is protected only by your internal network and header hygiene. See the mTLS Guide for handshake and certificate lifecycle detail.

IP allowlisting

The receiver, its firewall or its WAF accepts connections only from the provider's published egress addresses. GitHub publishes its webhook delivery addresses through GET /meta and says it changes them from time to time; Stripe publishes a webhook IP list with JSON and text downloads and gives seven days' notice of changes through its API announce mailing list; Svix publishes regional source ranges but states static source IPs are not guaranteed on every pricing tier; Twilio states it has no fixed range of addresses that issue webhooks and suggests receiving on a DMZ load balancer. The check is cheap and sheds scanner traffic, but says nothing about who controls the request inside that range.

Side-by-side comparison

DimensionHMAC signingmTLSIP allowlisting
What it provesA holder of the shared secret produced these exact bytesA holder of the certificate's private key opened this connectionThe connection came from a listed address range
Binds to message contentYes, body plus any signed timestamp and IDNo, only the connectionNo
Distinguishes tenants of the same providerYes, the secret is per endpointUsually no: one provider certificate serves every customer, so tenancy must come from the payloadNo: every customer shares the egress ranges
Replay protectionYes when the scheme signs a timestamp and ID and the receiver checks themNone at message levelNone
Where it is enforcedApplication code or webhook gatewayTLS terminator (load balancer, ingress, proxy)Firewall, security group, WAF or edge
Secret held by receiverShared secret (v1) or public key only (asymmetric)Trust anchors only, nothing secretNothing secret
Main operational burdenSecret storage and rotation, raw-body handlingTrust store, header forwarding, terminator configurationKeeping ranges current, false rejects after provider changes
Provider supportNear universalOffered by some providersDepends on whether the provider publishes stable ranges

Threat model: which check stops which attack

"Stops" means the check alone rejects the forged request; "partial" means it raises cost or narrows the source.

ThreatHMAC signingmTLSIP allowlisting
Internet scanner or attacker with no provider account posts a forged eventStopsStopsStops
Attacker with their own account at the same provider points it at your URLStops (their secret differs)Does not stop: the provider's certificate is the same for every customerDoes not stop: traffic comes from the same ranges
Captured valid request resent laterStops with timestamp tolerance and ID deduplicationDoes not stop if resent through a permitted pathDoes not stop
Signing secret leaked from a repository, CI log or dashboardFails open until rotatedUnaffected (no shared secret)Partial: attacker must also originate from the ranges, which a same-provider account achieves
Body tampered by an intermediaryStopsStops on the wire; blind to changes after the terminatorDoes not stop
Direct access to the application behind the terminator, bypassing itStops (verification is in the app)Does not stop if the forwarded identity header can be set by the callerDoes not stop if the internal path is unfiltered
Provider changes egress addresses or certificate chainUnaffectedOutage risk if the trust store or SAN check is staleOutage risk if ranges are stale

The same-provider row is why neither mTLS nor an allowlist can stand alone for multi-tenant providers. The leaked-secret row is why mTLS is a strong second layer on HMAC: an attacker then needs the provider's private key too.

Failure modes and a worked scenario for each

HMAC signing

  • Fail-open configuration: code that verifies only "if a secret is configured" accepts everything when the variable is missing after a redeploy.
  • Weak freshness: no timestamp check, or a tolerance of hours, turns any logged request into a reusable token. Stripe warns that a tolerance of 0 disables the recency check entirely.
  • Legacy schemes accepted: Stripe tells receivers to ignore every scheme except v1 to prevent downgrade attacks.
  • Shared secret everywhere: one value across staging and production means a leak in the weakest environment forges events in the strongest.

Worked scenario: a payments receiver verifies Stripe signatures correctly, but the signing secret is also present in a CI variable that a build script printed to a log. An attacker who reads the log can sign arbitrary checkout.session.completed events. Detection comes from fulfilment events with no matching provider-side delivery. Response: roll the secret with immediate expiry and re-check every order fulfilled since the exposure against the Stripe API. Re-fetching objects before high-impact actions would have made the forged events no-ops.

mTLS

  • Spoofable identity header: the terminator sets X-Client-Certificate-SAN, but a second ingress path or a misconfigured proxy lets clients send that header themselves.
  • Loose name matching: accepting any subject under the provider's domain, or any certificate that chains to a public root, admits certificates the provider never intended for webhook delivery. Slack's documentation requires an exact match on one name.
  • Optional client certificates: terminators configured to request but not require a certificate pass unauthenticated connections through with an empty header.

Worked scenario: a team moves Slack verification from HMAC to mTLS on a shared ingress controller. A second hostname on the same controller routes to the same service without client certificate validation, and the application trusts the SAN header on both. An attacker posts directly to the second hostname with a forged header and triggers slash command actions. The fix is to strip the header at every ingress, require client certificates on the webhook hostname only, and keep HMAC verification in place so that mTLS is an additional factor rather than a replacement.

IP allowlisting

  • Allowlist as the only check: any account at the provider can deliver to your endpoint from permitted addresses.
  • Manual lists: ranges copied once into a security group go stale; GitHub advises updating the list periodically and monitoring its API.
  • Trusting forwarded headers: allowlisting on X-Forwarded-For instead of the actual peer address lets clients choose their apparent source.

Worked scenario: an internal deployment service accepts GitHub push webhooks behind a firewall that allows only the webhook delivery ranges from GET /meta, with no secret configured. An attacker creates a repository in their own account, adds a webhook pointing at the service's URL (found in a public issue) and sends push events naming internal repositories. The deployment service builds and deploys attacker-chosen refs. Adding signature verification with a per-webhook secret closes the hole; the allowlist stays as a filter.

Layering patterns by risk tier

TierExample eventsMinimumRecommended layering
InformationalNotifications, analytics, chat messages that only displaySignature with timestamp checkSignature, deduplication, rate limiting at the edge
State-changingTicket updates, CI triggers, CRM syncSignature, timestamp, deduplication, fail closedPlus allowlist at the edge where the provider publishes stable ranges, and tenant ownership checks on referenced objects
High-impactPayment fulfilment, payouts, access grants, deploymentsAll of the above plus re-fetch of the object from the provider API before actingPlus mTLS where offered, a dedicated webhook gateway, and alerting on unusual event volumes
Private network receiverWebhooks into on-premises or VPC-only servicesSignature verification at a DMZ or gateway, not on the internal serviceAllowlist at the perimeter, gateway verifies and forwards over internal mTLS

Small vs large organisations: a small team with a few integrations gets most of the value from official verification libraries, a secrets manager and an edge allowlist where available. A large organisation should terminate all inbound webhooks at one gateway that verifies, deduplicates and queues events, so provider secrets never reach internal services. See the API Gateway Security Guide.

Provider support to plan around

Providers are listed alphabetically. The table reflects each provider's public documentation as of November 2026; confirm current details before designing around them.

ProviderDocumented sender authenticationSource address guidance
GitHubHMAC-SHA256 in X-Hub-Signature-256 with a per-webhook secret; X-GitHub-Delivery for replay detectionDelivery addresses via GET /meta; GitHub states it does not recommend allowing by IP address and advises monitoring its API if you do
Google Cloud Pub/Sub (push)Google-signed OIDC JWT in the Authorization header; verify signature, aud, email and email_verifiedFirewalls must permit push requests; authentication is carried in the token
SlackHMAC-SHA256 signing secret with a five-minute timestamp window, or mTLS with SAN platform-tls-client.slack.comIdentity carried in the signature or client certificate
StripeHMAC-SHA256 v1 signatures over timestamp and payload with per-endpoint secretsPublished webhook IP list in JSON and text, seven days' notice of changes via mailing list; Stripe advises using IP allowlisting and signature verification together
Svix-delivered webhooksStandard Webhooks style signatures (see the provider's verification docs)Published regional source ranges, with static IPs on Pro and Enterprise tiers
TwilioHMAC-SHA1 in X-Twilio-Signature keyed with the account auth token; SDK validation recommendedReceive on a DMZ load balancer and proxy inward, as Twilio uses no fixed webhook range

For providers you build yourself, prefer an asymmetric scheme (Standard Webhooks v1a with ed25519, or RFC 9421 HTTP Message Signatures with created, expires and nonce parameters), so receivers hold no secret that could forge events to anyone else.

Rotation of webhook secrets as non-human identity

Every mechanism creates a credential somebody must own. Treat each as an entry in the non-human identity inventory with the provider, endpoint, owner, storage location and the actions it can trigger.

CredentialBlast radius if exposedRotation modelExposure response
HMAC signing secretForged events to that endpoint until rotatedReceiver accepts a list of secrets; provider overlap window (Stripe lets the previous secret stay active for up to 7 days; Standard Webhooks signs with old and new keys)Roll with immediate expiry, replay-check events since exposure
Account credential used as signing key (Twilio auth token model)Forged webhooks and full API accessRotate as an API credentialTreat as an account compromise
Provider client certificate (mTLS)Held by the provider; receiver holds trust anchors onlyTrack the provider's chain changes; keep trust bundle currentRemove trust in the affected chain, fall back to signature only
Asymmetric public keyNone if leaked; private key stays with the senderPublish new key before switching, accept both brieflySender rotates; receivers refresh keys
Allowlist entriesNot a credential, but stale entries widen accessAutomated refresh from provider feedsRemove ranges no longer published

The rotation sequence (add new secret to the receiver, roll at the provider, watch failures, remove the old one) is in the Secrets Rotation Runbook Template. The design point: receivers that accept multiple secrets make rotation routine, and mTLS on top of HMAC turns a secret leak from an emergency into a scheduled rotation.

Implementing and moving between models

  1. Inventory: list every inbound webhook, the mechanisms its provider offers, what is enforced and its highest-impact action.
  2. Classify by tier: apply the risk tier table and record the target layering for each route.
  3. Add signatures in log-only mode: compute and log verification results for one to two weeks, fix raw-body and proxy issues, then enforce and fail closed.
  4. Add timestamp and deduplication: store delivery IDs for longer than the tolerance window and reject repeats.
  5. Automate allowlists: where providers publish ranges, refresh them from the feed on a schedule and alert when a refresh fails, rather than editing rules by hand.
  6. Pilot mTLS on one route: require client certificates on a dedicated hostname, strip the identity header at every ingress, test with the provider's delivery tools, and keep HMAC enforced throughout.
  7. Roll back safely: each layer switches independently: return a route to log-only signatures, relax mTLS on the dedicated hostname or widen the allowlist, without removing code.

Decision checklist

  • Does the provider sign messages? If yes, enforce it everywhere. If no, re-fetch every object from the provider API before acting and press the provider for signing.
  • Is the provider multi-tenant? If yes, mTLS and allowlists cannot distinguish your integration from another customer's; signatures or payload-to-tenant checks must.
  • What happens if the secret leaks? If the answer is money moves or access is granted, add re-fetch and, where offered, mTLS.
  • Does the receiver sit in a private network? Put verification at the perimeter gateway and use the allowlist there.
  • Does the provider publish stable ranges with change notice? If not, an allowlist will cause outages; skip it.

Detection and measurement

  • Log by layer: firewall drops, TLS handshake failures and signature failures separately, to tell probing from misconfiguration.
  • Correlate with provider delivery logs: processed events with no matching provider-side delivery suggest a leaked secret.

Metrics that show the design is working:

  • Signature coverage: percentage of webhook routes enforcing signature, timestamp and deduplication (target 100%).
  • Layering conformance: percentage of high-impact routes meeting the tier's recommended layering.
  • Allowlist freshness: hours since the last successful automated refresh per provider.
  • Rejected requests by layer and reason: per thousand deliveries, with thresholds.
  • Time to rotate after exposure: hours from detection to the old secret being invalid.

Common failure patterns

  • Replacing signatures with mTLS or an allowlist: both authenticate the provider, not your integration, so a same-provider account gets through.
  • Treating a secret URL as authentication: URLs leak through logs, chat and screenshots. See the Webhook URL Leak Check.
  • Trusting forwarded identity: client certificate or source IP headers that callers can set themselves.
  • Acting on payload fields: trusting amounts, account IDs or roles in the event instead of re-fetching high-impact objects.

Framework mapping

ConcernNIST SP 800-53 Rev. 5NIST CSF 2.0ATT&CK v20
Authenticating the sending service (HMAC, mTLS, signed token)IA-9 Service Identification and AuthenticationPR.AA-03T1078 Valid Accounts
Message integrity and freshnessSC-8 Transmission Confidentiality and Integrity, SC-23 Session AuthenticityPR.DS-02T1557 Adversary-in-the-Middle
Source address filteringSC-7 Boundary Protection, AC-4 Information Flow EnforcementPR.IR-01
Secret and key lifecycleIA-5 Authenticator Management, SC-12 Cryptographic Key Establishment and ManagementPR.AA-01T1552.001 Credentials In Files
Validating payloads before actingSI-10 Information Input ValidationPR.AA-05
Logging verification outcomesAU-2 Event Logging, SI-4 System MonitoringDE.CM-09

In ISO/IEC 27001:2022 Annex A the closest controls are 5.17 Authentication information, 8.20 Networks security, 8.24 Use of cryptography and 8.15 Logging.

Practitioner checklist

  • Enforce message signatures on every webhook route and fail closed when the secret cannot be loaded.
  • Check signed timestamps within about five minutes and deduplicate on the delivery or event ID.
  • Never use mTLS or an allowlist as the only check for a multi-tenant provider.
  • Where you add mTLS, require client certificates, match the exact provider name and strip identity headers at every ingress.
  • Refresh provider IP ranges automatically and allowlist on the real peer address, not forwarded headers.
  • Re-fetch high-impact objects from the provider API before acting on an event.
  • Register each signing secret as a non-human credential with owner, store and rotation date; build receivers that accept multiple secrets.
  • Log rejections by layer and reason and correlate processed events with provider delivery logs.
  • When you are the sender, offer asymmetric signatures so receivers hold no forging secret.

Standards and references

Related NHI Mgmt Group resources: Webhook Secrets Security Guide · mTLS Guide · mTLS vs Signed Tokens for Service Authentication · Web Bot Auth and HTTP Message Signatures for Agents · Secrets Management Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 14 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org