Express.jsNode.js / JavaScript
Express.js Webhook Handler Guide: Fix body-parser & Verify Signatures
Learn how to configure Express.js with `express.raw({ type: "application/json" })` for webhook signature verification without breaking standard JSON routes.
Direct Answer / Quick Implementation Guide
In Express.js, apply `express.raw({ type: "application/json" })` specifically to your `/api/webhook` route BEFORE applying global `app.use(express.json())`. This ensures the raw `Buffer` is available on `req.body` for cryptographic HMAC verification.
Essential Implementation Takeaways
- •Mount `express.raw({ type: "application/json" })` before global `express.json()`.
- •Use `crypto.timingSafeEqual` to compare computed hashes against headers.
- •Convert raw buffer to JSON after signature validation via `JSON.parse(req.body.toString())`.
- •Respond with `res.status(200).send({ received: true })`.
Common Gotchas in Express.js & How to Fix Them
Placing `app.use(express.json())` at top of file
Fix:Move `app.post("/webhook", express.raw(...))` above all global body parsing middleware.
Complete Production Boilerplate
Node.js / JavaScript// server.js (Express.js Webhook Receiver)
const express = require('express');
const crypto = require('crypto');
const app = express();
// 1. Webhook route with raw body buffer
app.post('/api/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-hub-signature-256'];
const secret = process.env.WEBHOOK_SECRET;
if (!signature) {
return res.status(400).send('Missing signature');
}
// Compute HMAC digest using raw buffer
const hmac = crypto.createHmac('sha256', secret);
const digest = 'sha256=' + hmac.update(req.body).digest('hex');
const isValid = crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
if (!isValid) {
return res.status(401).send('Signature mismatch');
}
// Parse JSON now that signature is verified
const event = JSON.parse(req.body.toString('utf8'));
console.log('Received valid event:', event);
res.status(200).json({ received: true });
});
// 2. Global JSON parser for rest of your API
app.use(express.json());
app.listen(3000, () => console.log('Server running on port 3000'));Step-by-Step Setup Guide
1
Define the webhook route before registering global middleware.
2
Attach `express.raw({ type: "application/json" })` to the webhook route.
3
Perform timing-safe HMAC validation with Node’s built-in `crypto` module.
4
Parse the verified buffer with `JSON.parse(req.body.toString())`.
5
Acknowledge with HTTP 200.
How to Test Locally on Your Machine
- Run `node server.js` locally on port 3000.
- In SafeWebhook, copy the cURL export command for any captured webhook.
- Execute the cURL command targeting `http://localhost:3000/api/webhook`.
- Verify the event logs in your terminal.
Frequently Asked Questions: Express.js Webhooks
Can I capture the raw body inside express.json() verify callback?
Yes, you can use `express.json({ verify: (req, res, buf) => { req.rawBody = buf; } })` to attach the buffer to all incoming requests.
Test Your Express.js Webhook Handler Live
Capture payloads, simulate errors, and replay directly to your localhost server.