typescriptintermediate

Webhook Signature Verification

Verifies HMAC-SHA256 webhook signatures to ensure payloads are from trusted sources.

typescript
import { createHmac, timingSafeEqual } from 'crypto';
import { Request, Response, NextFunction } from 'express';

export function verifyWebhookSignature(secret: string, headerName = 'x-signature-256') {
  return (req: Request, res: Response, next: NextFunction) => {
    const signature = req.headers[headerName] as string;
    if (!signature) {
      return res.status(401).json({ error: 'Missing signature' });
    }

    const rawBody = JSON.stringify(req.body);
    const expected = `sha256=${createHmac('sha256', secret).update(rawBody).digest('hex')}`;

    const sigBuffer = Buffer.from(signature);
    const expectedBuffer = Buffer.from(expected);

    if (sigBuffer.length !== expectedBuffer.length || !timingSafeEqual(sigBuffer, expectedBuffer)) {
      return res.status(403).json({ error: 'Invalid signature' });
    }

    next();
  };
}

Use Cases

  • GitHub webhook handlers
  • Payment gateway callbacks

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.