@bernierllc/webhook-receiver
v1.2.2
Published
Core HTTP endpoint functionality for receiving and processing webhooks with signature validation
Readme
@bernierllc/webhook-receiver
Core HTTP endpoint functionality for receiving and processing webhooks with signature validation.
Installation
npm install @bernierllc/webhook-receiverUsage
Basic Webhook Receiver
import { WebhookReceiver } from '@bernierllc/webhook-receiver';
const receiver = new WebhookReceiver({
maxPayloadSize: 1024 * 1024, // 1MB
signatureHeader: 'x-webhook-signature',
signatureSecret: process.env.WEBHOOK_SECRET,
signatureAlgorithm: 'hmac-sha256',
replayProtection: true,
timestampTolerance: 300 // 5 minutes
});
// Process incoming webhook
const payload = await receiver.processRequest({
method: 'POST',
headers: request.headers,
body: request.body,
url: request.url
});
console.log('Webhook received:', payload.event, payload.source);GitHub Webhook Example
const githubReceiver = new WebhookReceiver({
signatureHeader: 'x-hub-signature-256',
signatureSecret: process.env.GITHUB_WEBHOOK_SECRET,
signatureAlgorithm: 'hmac-sha256',
customValidator: async (payload) => {
// GitHub-specific validation
return payload.headers['user-agent']?.startsWith('GitHub-Hookshot/');
}
});Stripe Webhook Example
const stripeReceiver = new WebhookReceiver({
signatureHeader: 'stripe-signature',
signatureSecret: process.env.STRIPE_WEBHOOK_SECRET,
signatureAlgorithm: 'hmac-sha256',
timestampHeader: 'stripe-signature', // Contains timestamp
timestampTolerance: 300
});Features
- Multiple Signature Algorithms: HMAC-SHA256, HMAC-SHA1, JWT, custom validation
- Automatic Source Detection: GitHub, Stripe, GitLab, Bitbucket, Slack, Discord
- Replay Protection: Timestamp validation with configurable tolerance
- Content Type Support: JSON, form-data, raw text, XML
- Size Limits: Configurable payload size restrictions
- Framework Agnostic: Works with Express, Fastify, Next.js, Edge functions
API Reference
WebhookReceiver
Constructor Options
interface ReceiverOptions {
maxPayloadSize?: number; // Max payload size in bytes (default: 10MB)
signatureHeader?: string; // Header containing signature
signatureSecret?: string; // Secret for signature validation
signatureAlgorithm?: 'hmac-sha256' | 'hmac-sha1' | 'jwt' | 'custom';
timestampHeader?: string; // Header containing timestamp
timestampTolerance?: number; // Timestamp tolerance in seconds
replayProtection?: boolean; // Enable replay protection
customValidator?: (payload: WebhookPayload) => Promise<boolean>;
}Methods
processRequest(request: WebhookRequest): Promise<WebhookPayload>validateSignature(payload: WebhookPayload): Promise<boolean>validateTimestamp(payload: WebhookPayload): Promise<boolean>
Utility Functions
// Signature validation
validateHmacSignature(payload: string | Buffer, signature: string, secret: string, algorithm: 'sha256' | 'sha1'): boolean
// Request parsing
parseHeaders(headers: Record<string, string>): ParsedHeaders
parsePayloadData(body: Buffer | string, contentType?: string): any
// Source detection
detectWebhookSource(headers: Record<string, string>): string
detectWebhookEvent(headers: Record<string, string>, data: any): stringSupported Webhook Sources
- GitHub (
x-github-event,x-hub-signature-256) - Stripe (
stripe-signature) - GitLab (
x-gitlab-event) - Bitbucket (
x-event-key) - Slack (User-Agent detection)
- Discord (User-Agent detection)
- Generic webhook detection
Security Features
- Signature Validation: HMAC-SHA256/SHA1, JWT token validation
- Replay Protection: Timestamp validation with configurable tolerance
- Input Validation: Payload size limits, content-type validation
- Header Sanitization: Removes potentially dangerous headers
- Timing Attack Prevention: Constant-time signature comparison
Error Handling
All validation errors throw WebhookError with appropriate HTTP status codes:
try {
const payload = await receiver.processRequest(request);
} catch (error) {
if (error instanceof WebhookError) {
// Return appropriate HTTP status
return new Response(error.message, { status: error.statusCode });
}
throw error;
}Integration Status
Logger Integration
Status: Optional (recommended for webhook monitoring)
Justification: While this package can function without logging, it's highly recommended to integrate @bernierllc/logger for webhook event monitoring. Webhook receivers handle security-critical operations (signature validation, replay protection) and logging these events helps with security auditing, debugging, and threat detection. However, the package is designed to work without logging for environments where logging isn't available.
Pattern: Optional integration - package works without logger, but logger enhances security monitoring capabilities.
Example Integration:
import { Logger } from '@bernierllc/logger';
import { WebhookReceiver } from '@bernierllc/webhook-receiver';
const logger = new Logger({ service: 'webhook-receiver' });
const receiver = new WebhookReceiver({ /* config */ });
// Log webhook events
receiver.on('webhook:received', (event) => {
logger.info('Webhook received', { source: event.source, timestamp: event.timestamp });
});NeverHub Integration
Status: Optional (recommended for webhook orchestration)
Justification: While this package can function without NeverHub, it's highly recommended to integrate @bernierllc/neverhub-adapter for webhook orchestration and event publishing. Webhook receivers often need to coordinate with other services, and NeverHub provides a service mesh for publishing webhook events that other services can subscribe to. However, the package is designed to work without NeverHub for simpler use cases.
Pattern: Optional integration - package works without NeverHub, but NeverHub enhances webhook orchestration capabilities.
Example Integration:
import { NeverHubAdapter } from '@bernierllc/neverhub-adapter';
import { WebhookReceiver } from '@bernierllc/webhook-receiver';
const neverhub = new NeverHubAdapter({ service: 'webhook-receiver' });
const receiver = new WebhookReceiver({ /* config */ });
// Publish webhook events to NeverHub
receiver.on('webhook:validated', async (event) => {
await neverhub.publish('webhook.received', {
source: event.source,
payload: event.payload,
timestamp: event.timestamp
});
});Docs-Suite Integration
Status: Ready
Format: TypeDoc-compatible JSDoc comments are included throughout the source code. All public APIs are documented with examples and type information.
License
Copyright (c) 2025 Bernier LLC. All rights reserved.
