Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Webhook Signatures Laravel Package

jeffersongoncalves/laravel-webhook-signatures

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require jeffersongoncalves/laravel-webhook-signatures
    

    Publish the config file (if needed):

    php artisan vendor:publish --provider="JeffersonGoncalves\LaravelWebhookSignatures\WebhookSignaturesServiceProvider"
    
  2. First Use Case: Verify a webhook payload from Mailgun (example):

    use JeffersonGoncalves\LaravelWebhookSignatures\Facades\WebhookSignatures;
    
    $payload = file_get_contents('php://input');
    $headers = getallheaders();
    
    $isValid = WebhookSignatures::verify(
        $payload,
        $headers['X-Signature'],
        'your-mailgun-webhook-secret'
    );
    
    if ($isValid) {
        // Process the webhook
    }
    
  3. Key Config: Check config/webhook-signatures.php for supported services (Mailgun, SendGrid, etc.) and their default headers.


Implementation Patterns

Common Workflows

  1. Middleware for Automatic Verification: Create a middleware to validate all incoming webhooks:

    namespace App\Http\Middleware;
    
    use Closure;
    use JeffersonGoncalves\LaravelWebhookSignatures\Facades\WebhookSignatures;
    
    class VerifyWebhookSignature
    {
        public function handle($request, Closure $next)
        {
            $service = config('webhook-signatures.services.mailgun.secret');
            $isValid = WebhookSignatures::verify(
                $request->getContent(),
                $request->header('X-Signature'),
                $service
            );
    
            if (!$isValid) {
                abort(403, 'Invalid webhook signature');
            }
    
            return $next($request);
        }
    }
    

    Register in app/Http/Kernel.php:

    protected $routeMiddleware = [
        'verify.webhook' => \App\Http\Middleware\VerifyWebhookSignature::class,
    ];
    

    Use in routes:

    Route::post('/webhook/mailgun', [WebhookController::class, 'handle'])
        ->middleware('verify.webhook');
    
  2. Dynamic Service Configuration: Override service-specific settings per route:

    Route::post('/webhook/sendgrid', [WebhookController::class, 'handle'])
        ->middleware(function ($request, $next) {
            config(['webhook-signatures.services.sendgrid.secret' => 'your-sendgrid-secret']);
            return $next($request);
        });
    
  3. Event-Based Processing: Dispatch events after validation:

    if ($isValid) {
        event(new WebhookReceived($payload, $headers));
    }
    

Integration Tips

  • Laravel Valet/Homestead: Test locally by forwarding webhook traffic to your dev environment.
  • Logging: Log failed validations for debugging:
    if (!$isValid) {
        \Log::warning('Webhook validation failed', [
            'service' => 'mailgun',
            'signature' => $headers['X-Signature'] ?? null,
        ]);
    }
    
  • Testing: Use WebhookSignatures::fake() for unit tests:
    public function test_webhook_validation()
    {
        WebhookSignatures::fake(['mailgun' => true]);
    
        $response = $this->post('/webhook/mailgun', [], [
            'X-Signature' => 'valid-sig',
        ]);
    
        $response->assertOk();
    }
    

Gotchas and Tips

Pitfalls

  1. Header Case Sensitivity: Some services (e.g., AWS SNS) use X-Amz-Signature instead of X-Signature. Ensure your config matches the exact header name.

  2. Payload Encoding: Always use file_get_contents('php://input') or $request->getContent()—never json_decode($request->input()) directly, as it may strip headers or alter payload structure.

  3. Secret Management: Avoid hardcoding secrets in middleware. Use Laravel’s config() or environment variables:

    $secret = config('services.mailgun.webhook_secret');
    
  4. Time Synchronization: Webhook signatures rely on timestamps. Ensure your server’s clock is synchronized (e.g., via NTP).

Debugging

  • Signature Mismatch: If validation fails, compare the computed signature with the received one:

    $computedSig = WebhookSignatures::computeSignature($payload, $secret);
    \Log::debug('Expected:', [$headers['X-Signature']]);
    \Log::debug('Computed:', [$computedSig]);
    
  • Service-Specific Quirks:

    • SendGrid: Uses X-SendGrid-Signature and includes a timestamp in the payload.
    • AWS SNS/SES: Requires the X-Amz-Signature-Version header (default: 2).

Extension Points

  1. Custom Services: Extend the package by adding a new service class:

    namespace App\Services;
    
    use JeffersonGoncalves\LaravelWebhookSignatures\Contracts\WebhookService;
    
    class CustomService implements WebhookService
    {
        public function verify($payload, $signature, $secret)
        {
            // Custom logic
        }
    }
    

    Register in config/webhook-signatures.php:

    'services' => [
        'custom' => [
            'secret' => env('CUSTOM_WEBHOOK_SECRET'),
            'class' => \App\Services\CustomService::class,
        ],
    ];
    
  2. Override Default Headers: Customize headers per service in the config:

    'services' => [
        'mailgun' => [
            'secret' => env('MAILGUN_SECRET'),
            'header' => 'X-Mailgun-Signature', // Override default
        ],
    ];
    
  3. Algorithm Flexibility: If the package doesn’t support your signing algorithm (e.g., HMAC-SHA512), fork the package or extend the computeSignature method.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log