The most frequent cause of 401 Unauthorized webhook failures in Node and TypeScript backends is verifying the HMAC-SHA256 signature against JSON.stringify(req.body) instead of the exact raw UTF-8 byte stream transmitted by Stripe or Shopify.
Whenever a global JSON body parser deserializes and re-serializes a payload, subtle differences in key spacing, escaped characters, or scientific notation produce a completely different SHA-256 digest.
import crypto from ' node:crypto ' ;
export function verifyStripeWebhookRawHmac ({ rawBodyBuffer , sigHeader , secret , nowSec , toleranceSec = 300 }) { const parts = Object . fromEntries ( String ( sigHeader || '' ). split ( ' , ' ). map (( kv ) => kv . trim (). split ( ' = ' )) ); const ts = Number ( parts . t ); if ( ! Number . isInteger ( ts ) || Math . abs ( nowSec - ts ) > toleranceSec ) return false ; const signedPayload = ` ${ ts } . ${ rawBodyBuffer . toString ( ' utf8 ' )} ` ; const expected = crypto . createHmac ( ' sha256 ' , secret ).…