This site is not affiliated with or endorsed by Cloudflare, Inc. It showcases deployable experiments across most Cloudflare products.
Edge Platform

Webhook Signature Verifier

Verify HMAC-SHA256 webhook signatures with timing-safe comparison at the edge - Stripe/GitHub-style webhook auth

Accept a raw payload, secret, signature header value, and algorithm. Computes the expected HMAC (Stripe/GitHub sha256= hex style) and returns whether it matches using a timing-safe compare.

Features

  • POST /verify - HMAC-SHA256 verification with clear comparison explanation
  • Supports prefixed signatures (sha256=...) and raw hex
  • Uses Web Crypto at the edge; no external libraries

API Reference

POST /verify

payload string (required) - Raw request body as received.

secret string (required) - Shared signing secret.

signature string (required) - Signature from the webhook header.

algorithm string (optional) - Default sha256.

Example Request

curl -X POST "https://your-worker.workers.dev/verify" \
  -H "Content-Type: application/json" \
  -d '{"payload":"{\"id\":1}","secret":"whsec_test","signature":"sha256=..."}'

Success Response

{
  "match": true,
  "algorithm": "sha256",
  "expectedSignature": "sha256=...",
  "providedSignature": "sha256=...",
  "explanation": "Timing-safe comparison of 32-byte HMAC digests returned match."
}

Error Codes

  • 400 - INVALID_BODY, MISSING_FIELD, INVALID_ALGORITHM

Use Cases

  • Debug Stripe, GitHub, or Shopify webhook signature mismatches
  • Learn timing-safe HMAC verification patterns for Workers
  • Validate signing logic before wiring production webhook handlers

Limitations

  • HMAC-SHA256 only in this experiment
  • Secrets are sent in the request body; use only for debugging, not production traffic
  • No replay protection or timestamp validation

Use in your project

Copy these files into an existing Worker. Prefer Deployment to try the full experiment first. Source: apps/experiments/webhook-signature-verifier.

DependenciesNoneBindingsNonePlatformWeb Crypto
/** Allowed URL schemes for optional webhook URL validation helpers. */export const ALLOWED_SCHEMES = ["http:", "https:"] as const;/** * Validates and normalizes a URL. */export function validateUrl(input: string | undefined): string | null {  if (!input || typeof input !== "string") return null;  const trimmed = input.trim();  if (!trimmed) return null;  try {    const url = new URL(trimmed);    if (!ALLOWED_SCHEMES.includes(url.protocol as (typeof ALLOWED_SCHEMES)[number])) {      return null;    }    return url.href;  } catch {    return null;  }}

Deployment

Click the deploy button

Deploy to Cloudflare Workers

Configure bindings

See wrangler.json and the experiment README for required bindings.

Test your deployment

See the experiment README for curl examples.

Local Development

cd apps/experiments/webhook-signature-verifier
npm install
npm run dev

Configuration

No bindings required beyond the Workers runtime.

Cloudflare Features Used

On this page