← Back to all snippets
JAVASCRIPT

Build a Secure Webhook Receiver with Signature Verification

Learn to create a robust and secure webhook endpoint in Node.js Express, verifying incoming payloads using a shared secret signature (HMAC-SHA256).

const express = require('express');
const crypto = require('crypto');
const bodyParser = require('body-parser');

const app = express();
const WEBHOOK_SECRET = 'your_super_secret_key_here'; // Use a strong, unique secret

// Use rawBody for signature verification as express.json() parses it too early
app.use(bodyParser.json({
  verify: (req, res, buf) => {
    if (req.originalUrl === '/webhook-endpoint') { // Only apply to webhook endpoint
      req.rawBody = buf;
    }
  }
}));

app.post('/webhook-endpoint', (req, res) => {
  if (!req.rawBody) {
    return res.status(400).send('Webhook payload missing.');
  }

  const signature = req.headers['x-hub-signature-256'] || req.headers['x-signature']; // Common headers

  if (!signature) {
    return res.status(401).send('No signature provided.');
  }

  const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET);
  hmac.update(req.rawBody);
  const digest = `sha256=${hmac.digest('hex')}`; // Some providers prefix, e.g., 'sha256='

  if (digest !== signature) {
    console.warn('Webhook signature verification failed.');
    return res.status(403).send('Invalid signature.');
  }

  // If signature is valid, process the webhook payload
  console.log('Webhook payload received and verified:', req.body);
  // Example: Trigger further processing based on req.body.event_type

  res.status(200).send('Webhook received successfully.');
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Webhook receiver listening on port ${PORT}`);
});
How it works: This Node.js Express snippet creates a secure endpoint for receiving webhooks. It uses a shared secret and the `crypto` module to verify the integrity and authenticity of incoming webhook payloads via HMAC-SHA256 signature verification. By comparing the computed hash of the raw request body with the signature provided in the request headers, it ensures that the webhook originated from a trusted source and hasn't been tampered with.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs