JAVASCRIPT

Secure Webhook Receiver with Signature Verification

Build a secure Node.js Express webhook endpoint that verifies incoming requests using a shared secret signature, preventing spoofing and ensuring data integrity.

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

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

// IMPORTANT: Use a strong, unique secret key for your webhook
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET || 'your_super_secret_key_here';

// Raw body needed for signature verification
app.use(bodyParser.json({
    verify: (req, res, buf) => {
        req.rawBody = buf;
    }
}));

// Middleware to verify webhook signature
function verifyWebhookSignature(req, res, next) {
    const signature = req.headers['x-webhook-signature']; // Or 'stripe-signature', 'x-github-event', etc.
    if (!signature) {
        console.warn('Webhook received without signature.');
        return res.status(401).send('Unauthorized: Signature missing.');
    }

    const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET);
    // Ensure rawBody is available. For some webhooks, the signature is based on the JSON string itself.
    // If not available, you might need to stringify req.body or handle buffer differently.
    hmac.update(req.rawBody || JSON.stringify(req.body));
    const digest = 'sha256=' + hmac.digest('hex'); // Adjust prefix based on webhook provider (e.g., 'v1=', 'sha256=')

    if (digest !== signature) {
        console.warn(`Invalid webhook signature. Expected: ${digest}, Got: ${signature}`);
        return res.status(403).send('Forbidden: Invalid signature.');
    }

    console.log('Webhook signature verified successfully.');
    next();
}

app.post('/webhook', verifyWebhookSignature, (req, res) => {
    console.log('Received verified webhook payload:', req.body);
    // Process the webhook payload here
    // e.g., update database, trigger other services

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

app.listen(port, () => {
    console.log(`Webhook listener running at http://localhost:${port}`);
    console.log('Remember to set WEBHOOK_SECRET environment variable in production!');
});
How it works: This Node.js Express snippet sets up a secure webhook receiver. It uses a `bodyParser` to access the raw request body, which is crucial for signature verification. The `verifyWebhookSignature` middleware calculates an HMAC signature using a shared secret and compares it with the signature provided in the request header (`x-webhook-signature`). This process ensures that the incoming webhook payload has not been tampered with and originates from a trusted source.

Need help integrating this into your project?

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

Hire DigitalCodeLabs