PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteVerify a webhook against the exact body bytes its provider signed, before JSON middleware parses or changes them. Preserve the raw body, use that provider’s documented signature format and secret, compare signatures in constant time, and only then parse and process the payload.
Why JSON middleware can make a valid signature fail
A webhook signature is calculated from provider-defined input—often the original request body. JSON parsing converts bytes into an object; serializing that object again can produce different bytes, even when it represents the same data. Whitespace, escaping, or key formatting may differ. A signature calculated from the reconstructed body will not match one calculated from the bytes the provider sent.
Keep the original body available until verification is complete. Shopify explicitly requires the raw body for HMAC verification and says verification middleware must run before body-parser middleware. GitHub’s guidance likewise verifies the request body before processing it. Shopify’s verification guidance · GitHub’s delivery-validation guidance
Verification sequence
- Identify the provider and transport. Check the provider’s current signing specification or supported SDK helper. Do not assume another provider’s header, algorithm, or encoding applies. Shopify’s HTTPS HMAC procedure is distinct from its Amazon EventBridge and Google Cloud Pub/Sub delivery paths, which do not require that HTTPS HMAC check. Shopify’s delivery-structure documentation
- Preserve the body before parsing. In Express, mount route-specific raw-body handling before the global JSON parser, or configure parsing to retain the original bytes. Shopify’s manual Express example uses
express.raw()and warns that verification must run beforeexpress.json(). In a Fetch-style handler, read the body once as text or bytes and give that same representation to the verifier; request bodies are streams, so independent reads in multiple layers can consume the input. - Get the expected signature and secret from trusted configuration. Read the header specified by the provider and use the secret configured for that endpoint and environment. Reject a missing or malformed signature as the provider directs. Keep secrets server-side; GitHub recommends high-entropy secrets, secure storage, and avoiding hardcoding or committing them.
- Calculate and compare the provider-defined signature. Use the specified input, algorithm, and digest encoding. Compare the calculated value using a constant-time comparison, not ordinary string equality. GitHub names
secure_compareandcrypto.timingSafeEqualas examples; Shopify’s Express example also usescrypto.timingSafeEqual. - Reject mismatches before acting on the payload. Only after successful verification should you parse the retained body and route the event. A valid signature authenticates the signed input; it does not make duplicate processing safe.
- Make processing idempotent. Providers may retry deliveries after timeouts. Shopify recommends idempotent processing or deduplication using
X-Shopify-Webhook-Id. ItsX-Shopify-Event-Idcan correlate deliveries arising from one merchant action. Shopify’s verification guidance
GitHub and Shopify use different signature formats
These examples illustrate why verification must follow the provider’s specification rather than a generic webhook recipe. They describe the official GitHub and Shopify documentation, not every provider.
| Detail | GitHub | Shopify HTTPS |
|---|---|---|
| Signature header | X-Hub-Signature-256 |
X-Shopify-Hmac-SHA256 |
| Digest representation | Hex digest prefixed with sha256= |
Base64-encoded HMAC-SHA256 digest |
| Input and parsing implication | Verify the original payload before processing it; GitHub’s example reads the request body or text for verification. | Verify the raw request body; run verification before body-parser middleware. |
| Safe comparison examples | secure_compare or crypto.timingSafeEqual |
Shopify’s Express example uses crypto.timingSafeEqual. |
Sources: GitHub Docs and Shopify Developer Documentation.
Express: keep verification ahead of JSON parsing
The critical ordering is raw-body capture and verification first, JSON parsing afterward. Shopify’s manual Express example mounts express.raw() for the webhook route and cautions against running express.json() first. Apply the pattern to the route and content type your endpoint actually receives; a global parser registered earlier can consume or transform the body before the verification handler sees it. Consult Shopify’s current example for complete code and exact API details: Shopify webhook verification.
Rank #2
If the application must retain a global JSON parser, configure it to preserve the original bytes and pass those bytes—not a re-serialized object—to the verifier. Confirm that the retained value is the untouched request body, not the parsed object or a string produced from it later.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Diagnose a signature mismatch
A mismatch does not by itself prove the provider sent a bad signature. Check the request path through your application and infrastructure, then validate each provider-specific input:
Rank #3
- Middleware order: Did JSON parsing or another body-reading middleware run before raw-body capture or verification?
- Body integrity: Are you verifying the original bytes rather than a parsed-and-reserialized payload? Could a proxy or load balancer have modified the body?
- Secret selection: Is this the secret for the correct endpoint, provider, and environment?
- Header and digest format: Are you reading the provider’s exact header and handling its required algorithm, prefix, and encoding?
- Text encoding: If the implementation converts bytes to text, does it use the encoding required by the provider? GitHub’s guidance notes UTF-8 handling for language implementations that specify an encoding.
GitHub’s validation documentation also calls out secret, header, body, and encoding issues. Shopify’s guidance emphasizes raw-body handling and middleware order. GitHub Docs · Shopify Developer Documentation
Quick Recap
Best Value
Rank #4
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




