No articles found
Try different keywords or browse our categories
Fix: Error: Failed to verify webhook signature error
Quick fix for 'Failed to verify webhook signature' error. Learn how to properly implement webhook signature verification in your applications.
The ‘Failed to verify webhook signature’ error occurs when the signature sent with a webhook request doesn’t match the expected signature calculated using your secret key.
How the Error Happens
❌ Error Scenario:
// ❌ This causes signature verification to fail
// Webhook receives payload but signature doesn't match
app.post('/webhook', (req, res) => {
const signature = req.headers['x-signature']; // ❌ Wrong header name
const expected = calculateSignature(req.body, 'wrong-secret');
if (signature !== expected) {
throw new Error('Failed to verify webhook signature'); // ❌ Error thrown
}
});
✅ Quick Fix - Proper Signature Verification
Solution 1: Stripe Webhook Verification
// ✅ Stripe webhook verification
const stripe = require('stripe')('sk_test_...');
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const sig = req.headers['stripe-signature'];
const endpointSecret = 'whsec_...'; // ✅ Your webhook signing secret
let event;
try {
// ✅ Verify signature
event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
} catch (err) {
console.log(`Webhook signature verification failed. ${err.message}`);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
// ✅ Process webhook event
console.log('Received event:', event.type);
res.json({received: true});
});
Solution 2: Generic Signature Verification
// ✅ Generic webhook signature verification
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
// ✅ Create expected signature
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
// ✅ Compare signatures securely
return crypto.timingSafeEqual(
Buffer.from(`sha256=${expectedSignature}`, 'utf8'),
Buffer.from(signature, 'utf8')
);
}
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-hub-signature-256']; // ✅ Correct header
const secret = process.env.WEBHOOK_SECRET;
if (!verifySignature(req.body, signature, secret)) {
return res.status(401).send('Unauthorized: Invalid signature');
}
// ✅ Process webhook
res.status(200).send('OK');
});
Solution 3: GitHub Webhook Verification
// ✅ GitHub webhook verification
const crypto = require('crypto');
app.post('/github-webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-hub-signature-256'];
const payload = req.body;
const secret = process.env.GITHUB_WEBHOOK_SECRET;
// ✅ Calculate expected signature
const expectedSignature = `sha256=${crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex')}`;
// ✅ Verify signature
if (signature !== expectedSignature) {
return res.status(401).send('Unauthorized');
}
// ✅ Process GitHub event
const event = JSON.parse(payload.toString());
console.log(`Received ${event.action} event for ${event.repository.name}`);
res.status(200).send('OK');
});
Solution 4: PayPal Webhook Verification
// ✅ PayPal webhook verification
app.post('/paypal-webhook', express.json(), async (req, res) => {
try {
const webhookId = process.env.PAYPAL_WEBHOOK_ID;
const verifyUrl = 'https://api.paypal.com/v1/notifications/verify-webhook-signature';
const verificationBody = {
auth_algo: req.headers['paypal-auth-algo'],
cert_url: req.headers['paypal-cert-url'],
transmission_id: req.headers['paypal-transmission-id'],
transmission_sig: req.headers['paypal-transmission-sig'],
transmission_time: req.headers['paypal-transmission-time'],
webhook_id: webhookId,
webhook_event: req.body
};
// ✅ Verify with PayPal
const response = await fetch(verifyUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify(verificationBody)
});
const result = await response.json();
if (result.verification_status !== 'SUCCESS') {
return res.status(401).send('Invalid signature');
}
// ✅ Process webhook
res.status(200).send('OK');
} catch (error) {
console.error('Webhook verification error:', error);
res.status(500).send('Error processing webhook');
}
}); Related Articles
Fix: invalid_client OAuth error
Complete guide to fix 'invalid_client' OAuth error. Learn how to resolve client credentials and configuration issues in OAuth implementations.
Fix: Stripe webhook not triggering error
Quick fix for 'Stripe webhook not triggering' error. Learn how to properly configure and debug Stripe webhook endpoints.
How to Fix: 403 Forbidden Error - Complete Tutorial
Complete guide to fix 403 Forbidden errors. Learn how to resolve permission issues with practical solutions, authorization management, and best practices for secure API communication.