JAVASCRIPT

Securely Receiving and Verifying Webhook Payloads in Node.js

Set up a secure Node.js Express endpoint to receive webhook notifications and verify their authenticity using HMAC signatures, crucial for API integrations.

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

const app = express();
const port = 3000;

const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET; // Ensure this is stored securely

// Use raw body parser for webhook endpoints to get the raw body string
app.post('/webhook', bodyParser.raw({ type: 'application/json' }), (req, res) => {
  if (!WEBHOOK_SECRET) {
    console.error('WEBHOOK_SECRET not configured.');
    return res.status(500).send('Server error: Webhook secret not set.');
  }

  const signature = req.headers['x-hub-signature'] || req.headers['x-webhook-signature']; // Adjust header name as per provider
  if (!signature) {
    return res.status(401).send('No signature header provided.');
  }

  // Convert Buffer to string for HMAC calculation
  const payload = req.body.toString('utf8'); 

  const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET);
  hmac.update(payload);
  const digest = 'sha256=' + hmac.digest('hex'); // Adjust prefix as per provider, e.g., 'v1=' for GitHub

  if (digest === signature) {
    console.log('Webhook signature verified successfully!');
    const event = JSON.parse(payload); // Now parse the payload as JSON
    // Process the webhook event here
    console.log('Received webhook event:', event.type);
    res.status(200).send('Webhook received and processed.');
  } else {
    console.warn('Webhook signature verification failed!');
    res.status(403).send('Invalid webhook signature.');
  }
});

app.listen(port, () => {
  console.log(`Webhook listener running on http://localhost:${port}`);
});
How it works: This Node.js Express snippet demonstrates how to securely receive and verify webhook payloads. Many API providers send a signature along with the webhook payload, typically in an HTTP header, which is a hash of the payload generated using a shared secret. This code uses `body-parser.raw` to get the raw request body, computes its HMAC signature using `crypto.createHmac`, and compares it with the received signature. This process ensures that the webhook originated from the legitimate source and that its payload has not been tampered with during transit.

Need help integrating this into your project?

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

Hire DigitalCodeLabs