{"id":1470,"date":"2026-10-27T18:00:00","date_gmt":"2026-10-27T18:00:00","guid":{"rendered":"https:\/\/wade.one\/blog\/?p=1470"},"modified":"2026-10-27T18:00:00","modified_gmt":"2026-10-27T18:00:00","slug":"verify-webhook-signatures-before-parsing-away-the-evidence","status":"publish","type":"post","link":"https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/","title":{"rendered":"Verify Webhook Signatures Before Parsing Away the Evidence"},"content":{"rendered":"<p>A webhook can contain perfectly sensible JSON and still fail signature verification. If the signature covers the original request body, parsing that body and turning it back into JSON can change the bytes you are checking. The objects might look identical while the signed material is different.<\/p>\n<p>Stripe&#8217;s <a href=\"https:\/\/docs.stripe.com\/events\/manage-webhook-endpoints#signature-errors\">signature troubleshooting guide<\/a> is explicit about preserving the raw request body. Middleware can get there first, so I would check the route&#8217;s request handling before assuming the signing secret is wrong. Use the provider&#8217;s supported verification method with the original body, signature header and correct endpoint secret.<\/p>\n<p>Keep that boundary easy to follow. Verify the request before trusting its contents or performing an action, then pass the verified event into the application. Test a valid request and a modified one. There is no need to print secrets or complete event payloads into logs to prove which branch ran; a bounded diagnostic result is usually more useful anyway.<\/p>\n<p>Signature checks are much easier to maintain when the code shows exactly what was verified. A failed check should send you towards the input and endpoint configuration, rather than towards a convenient switch that disables verification. Preserve the evidence until the check has finished with it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A webhook can contain perfectly sensible JSON and still fail signature verification.<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[13],"tags":[295,294,293],"class_list":["post-1470","post","type-post","status-publish","format-standard","hentry","category-programming","tag-api-security","tag-stripe","tag-webhooks"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Verify Webhook Signatures Before Parsing Away the Evidence - wade.one<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Verify Webhook Signatures Before Parsing Away the Evidence - wade.one\" \/>\n<meta property=\"og:description\" content=\"A webhook can contain perfectly sensible JSON and still fail signature verification.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/\" \/>\n<meta property=\"og:site_name\" content=\"wade.one\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-27T18:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/Wade-Logo-cropped.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1518\" \/>\n\t<meta property=\"og:image:height\" content=\"1506\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@wadewomersley\" \/>\n<meta name=\"twitter:site\" content=\"@wadewomersley\" \/>\n<meta name=\"twitter:label1\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/27\\\/verify-webhook-signatures-before-parsing-away-the-evidence\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/27\\\/verify-webhook-signatures-before-parsing-away-the-evidence\\\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Verify Webhook Signatures Before Parsing Away the Evidence\",\"datePublished\":\"2026-10-27T18:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/27\\\/verify-webhook-signatures-before-parsing-away-the-evidence\\\/\"},\"wordCount\":212,\"publisher\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#\\\/schema\\\/person\\\/8b4739f8f8bb2cff5d792d4b8779fcc3\"},\"keywords\":[\"api-security\",\"stripe\",\"webhooks\"],\"articleSection\":[\"Programming\"],\"inLanguage\":\"en-GB\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/27\\\/verify-webhook-signatures-before-parsing-away-the-evidence\\\/\",\"url\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/27\\\/verify-webhook-signatures-before-parsing-away-the-evidence\\\/\",\"name\":\"Verify Webhook Signatures Before Parsing Away the Evidence - wade.one\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#website\"},\"datePublished\":\"2026-10-27T18:00:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/27\\\/verify-webhook-signatures-before-parsing-away-the-evidence\\\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/27\\\/verify-webhook-signatures-before-parsing-away-the-evidence\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/27\\\/verify-webhook-signatures-before-parsing-away-the-evidence\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/wade.one\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Verify Webhook Signatures Before Parsing Away the Evidence\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/wade.one\\\/blog\\\/\",\"name\":\"wade.one\",\"description\":\"wade womersley - york based software engineer\",\"publisher\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#\\\/schema\\\/person\\\/8b4739f8f8bb2cff5d792d4b8779fcc3\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wade.one\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#\\\/schema\\\/person\\\/8b4739f8f8bb2cff5d792d4b8779fcc3\",\"name\":\"Wade Womersley\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/02\\\/200px.png\",\"url\":\"https:\\\/\\\/wade.one\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/02\\\/200px.png\",\"contentUrl\":\"https:\\\/\\\/wade.one\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/02\\\/200px.png\",\"width\":202,\"height\":200,\"caption\":\"Wade Womersley\"},\"logo\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/02\\\/200px.png\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Verify Webhook Signatures Before Parsing Away the Evidence - wade.one","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/","og_locale":"en_GB","og_type":"article","og_title":"Verify Webhook Signatures Before Parsing Away the Evidence - wade.one","og_description":"A webhook can contain perfectly sensible JSON and still fail signature verification.","og_url":"https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/","og_site_name":"wade.one","article_published_time":"2026-10-27T18:00:00+00:00","og_image":[{"width":1518,"height":1506,"url":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/Wade-Logo-cropped.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_creator":"@wadewomersley","twitter_site":"@wadewomersley","twitter_misc":{"Estimated reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/#article","isPartOf":{"@id":"https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/"},"author":{"name":"","@id":""},"headline":"Verify Webhook Signatures Before Parsing Away the Evidence","datePublished":"2026-10-27T18:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/"},"wordCount":212,"publisher":{"@id":"https:\/\/wade.one\/blog\/#\/schema\/person\/8b4739f8f8bb2cff5d792d4b8779fcc3"},"keywords":["api-security","stripe","webhooks"],"articleSection":["Programming"],"inLanguage":"en-GB"},{"@type":"WebPage","@id":"https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/","url":"https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/","name":"Verify Webhook Signatures Before Parsing Away the Evidence - wade.one","isPartOf":{"@id":"https:\/\/wade.one\/blog\/#website"},"datePublished":"2026-10-27T18:00:00+00:00","breadcrumb":{"@id":"https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/wade.one\/blog\/2026\/10\/27\/verify-webhook-signatures-before-parsing-away-the-evidence\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/wade.one\/blog\/"},{"@type":"ListItem","position":2,"name":"Verify Webhook Signatures Before Parsing Away the Evidence"}]},{"@type":"WebSite","@id":"https:\/\/wade.one\/blog\/#website","url":"https:\/\/wade.one\/blog\/","name":"wade.one","description":"wade womersley - york based software engineer","publisher":{"@id":"https:\/\/wade.one\/blog\/#\/schema\/person\/8b4739f8f8bb2cff5d792d4b8779fcc3"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wade.one\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":["Person","Organization"],"@id":"https:\/\/wade.one\/blog\/#\/schema\/person\/8b4739f8f8bb2cff5d792d4b8779fcc3","name":"Wade Womersley","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/200px.png","url":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/200px.png","contentUrl":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/200px.png","width":202,"height":200,"caption":"Wade Womersley"},"logo":{"@id":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/200px.png"}}]}},"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":1180,"url":"https:\/\/wade.one\/blog\/2026\/04\/12\/the-hardest-part-of-serverless-is-not-the-code\/","url_meta":{"origin":1470,"position":0},"title":"The Hardest Part of Serverless Is Not the Code","author":"","date":"April 12, 2026","format":false,"excerpt":"The hard part of serverless is usually not writing the handler. It is understanding what failed, what the event looked like, and why the system changed underneath you.","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/wade.one\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1304,"url":"https:\/\/wade.one\/blog\/2026\/05\/16\/claude-code-routines-show-where-agent-automation-is-going\/","url_meta":{"origin":1470,"position":1},"title":"Claude Code Routines Show Where Agent Automation Is Going","author":"","date":"May 16, 2026","format":false,"excerpt":"Claude Code's web routines point to a future where coding agents are triggered by events, not only by a developer sitting at a terminal.","rel":"","context":"In &quot;AI&quot;","block_context":{"text":"AI","link":"https:\/\/wade.one\/blog\/category\/ai\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1168,"url":"https:\/\/wade.one\/blog\/2026\/04\/01\/why-i-still-like-serverless-for-small-teams\/","url_meta":{"origin":1470,"position":2},"title":"Why I Still Like Serverless for Small Teams","author":"","date":"April 1, 2026","format":false,"excerpt":"Serverless has real tradeoffs, but for small teams I still think it usually wins. The operational overhead stays low, the first version ships faster, and the mistakes are easier to afford early on.","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/wade.one\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":764,"url":"https:\/\/wade.one\/blog\/2015\/02\/07\/standardising-logging-and-parallelisation-in-multiple-languages\/","url_meta":{"origin":1470,"position":3},"title":"Standardising logging and parallelisation in multiple languages","author":"Wade","date":"February 7, 2015","format":false,"excerpt":"Over the last few days I've been working on interfaces to use across multiple programming languages to standardise how some things are done. This stemmed from a requirement to allow processing to be dealt with in any language from any other language. People do this all the time, it's nothing\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/wade.one\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/source-code-583537_640.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/source-code-583537_640.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/source-code-583537_640.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":151,"url":"https:\/\/wade.one\/blog\/2009\/09\/29\/peerblock-1-0-released-now-with-signed-driver\/","url_meta":{"origin":1470,"position":4},"title":"PeerBlock 1.0 Released &#8211; Now with signed driver","author":"Wade","date":"September 29, 2009","format":false,"excerpt":"PeerBlock was a \"spin off\" from PeerGuardian, a program that completely blocks access to certain IP addresses at the network level making it completely impossible to connect to them (or from people on those IP addresses to connect to you.) The reason I love this program so much is it\u2026","rel":"","context":"In &quot;News&quot;","block_context":{"text":"News","link":"https:\/\/wade.one\/blog\/category\/news\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1445,"url":"https:\/\/wade.one\/blog\/2026\/10\/26\/request-ids-are-useful-when-they-survive-the-whole-journey\/","url_meta":{"origin":1470,"position":5},"title":"Request IDs Are Useful When They Survive the Whole Journey","author":"Wade","date":"October 26, 2026","format":false,"excerpt":"A request ID in one log line is useful.","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/wade.one\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/posts\/1470","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/comments?post=1470"}],"version-history":[{"count":1,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/posts\/1470\/revisions"}],"predecessor-version":[{"id":1484,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/posts\/1470\/revisions\/1484"}],"wp:attachment":[{"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/media?parent=1470"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/categories?post=1470"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/tags?post=1470"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}