Webhook Verification
The SDK provides utilities to verify webhook signatures, ensuring that incoming webhook payloads genuinely originated from Felloh.
For general information about webhooks and the events available, see the Webhooks documentation.
Verifying Signatures
Felloh signs every webhook request with an HMAC-SHA256 signature sent in the X-Signature header. The SDK provides two
static methods on the Webhooks class to verify this signature:
Webhooks::verifyWebhookSignature— returnstrueorfalseWebhooks::assertWebhookSignature— throwsFellohWebhookSignatureErrorif invalid
Both use timing-safe comparison to prevent timing attacks.
Parameters
- Name
payloadrequired- Type
- string
- Description
The raw request body. Must not be parsed or modified — use the raw body as received.
- Name
signaturerequired- Type
- string
- Description
The value of the
X-Signatureheader from the webhook request.
- Name
secretrequired- Type
- string
- Description
Your webhook signing secret from the Felloh dashboard.
Boolean Check
use Felloh\Webhooks;
$isValid = Webhooks::verifyWebhookSignature(
payload: $rawRequestBody,
signature: $_SERVER['HTTP_X_SIGNATURE'],
secret: 'your-webhook-secret',
);
if (!$isValid) {
http_response_code(401);
echo 'Invalid signature';
exit;
}
// Process the webhook...
Assert (throws on failure)
use Felloh\Webhooks;
use Felloh\Exceptions\FellohWebhookSignatureError;
try {
Webhooks::assertWebhookSignature(
payload: $rawRequestBody,
signature: $_SERVER['HTTP_X_SIGNATURE'],
secret: 'your-webhook-secret',
);
} catch (FellohWebhookSignatureError $e) {
http_response_code(401);
echo 'Invalid signature';
exit;
}
// Signature is valid, process the webhook...
Laravel Example
When using Laravel, use $request->getContent() to get the raw request body for signature verification.
Laravel Webhook Handler
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Felloh\Webhooks;
use Felloh\Exceptions\FellohWebhookSignatureError;
Route::post('/webhooks/felloh', function (Request $request) {
try {
Webhooks::assertWebhookSignature(
payload: $request->getContent(),
signature: $request->header('X-Signature'),
secret: config('services.felloh.webhook_secret'),
);
} catch (FellohWebhookSignatureError $e) {
return response('Invalid signature', 401);
}
$event = $request->json()->all();
logger()->info('Webhook received', $event);
return response('OK', 200);
});
Symfony Example
When using Symfony, use $request->getContent() to get the raw request body.
Symfony Webhook Handler
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Felloh\Webhooks;
use Felloh\Exceptions\FellohWebhookSignatureError;
#[Route('/webhooks/felloh', methods: ['POST'])]
public function handleWebhook(Request $request): Response
{
try {
Webhooks::assertWebhookSignature(
payload: $request->getContent(),
signature: $request->headers->get('X-Signature'),
secret: $_ENV['FELLOH_WEBHOOK_SECRET'],
);
} catch (FellohWebhookSignatureError $e) {
return new Response('Invalid signature', 401);
}
$event = json_decode($request->getContent(), true);
// Process the webhook...
return new Response('OK', 200);
}
