Skip to main content

Webhook verification

shapeguard includes verifyWebhook() — HMAC signature verification for common providers.

Why this matters

  • Uses timingSafeEqual to prevent timing attacks
  • Stripe: validates timestamp tolerance (300 second window) to prevent replay attacks
  • All: fails fast with a clear 401 WEBHOOK_SIGNATURE_INVALID response

Stripe

app.post('/webhooks/stripe',
express.raw({ type: 'application/json' }), // ← raw body required for HMAC
verifyWebhook({ provider: 'stripe', secret: process.env.STRIPE_WEBHOOK_SECRET! }),
(req, res) => {
const event = JSON.parse(req.body.toString())
// Signature verified. Handle event.type here.
res.json({ received: true })
}
)

GitHub

app.post('/webhooks/github',
express.raw({ type: 'application/json' }),
verifyWebhook({ provider: 'github', secret: process.env.GITHUB_WEBHOOK_SECRET! }),
(req, res) => {
const payload = JSON.parse(req.body.toString())
const event = req.headers['x-github-event']
res.json({ received: true })
}
)

Custom provider

app.post('/webhooks/custom',
express.raw({ type: 'application/json' }),
verifyWebhook({
secret: process.env.CUSTOM_SECRET!,
algorithm: 'sha256',
headerName: 'x-my-signature',
prefix: 'sha256=',
encoding: 'hex',
toleranceSecs: 300,
}),
handler
)

Providers supported

ProviderHeaderAlgorithm
stripestripe-signaturesha256 HMAC + timestamp
githubx-hub-signature-256sha256 HMAC
shopifyx-shopify-hmac-sha256sha256 HMAC (base64)
twiliox-twilio-signaturesha1 HMAC
svixsvix-signaturesha256 HMAC
customconfigurableconfigurable