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 WebhookVerifier class to verify this signature:
WebhookVerifier.VerifySignature— returnstrueorfalseWebhookVerifier.AssertSignature— throwsFellohWebhookSignatureExceptionif invalid
Both use timing-safe comparison to prevent timing attacks. The methods accept either string or byte[] payloads.
Parameters
- Name
payloadrequired- Type
- string | byte[]
- 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
using Felloh;
var isValid = WebhookVerifier.VerifySignature(
payload: rawRequestBody,
signature: request.Headers["X-Signature"],
secret: "your-webhook-secret"
);
if (!isValid)
{
return Results.Unauthorized();
}
// Process the webhook...
Assert (throws on failure)
using Felloh;
using Felloh.Errors;
try
{
WebhookVerifier.AssertSignature(
payload: rawRequestBody,
signature: request.Headers["X-Signature"],
secret: "your-webhook-secret"
);
}
catch (FellohWebhookSignatureException)
{
return Results.Unauthorized();
}
// Signature is valid, process the webhook...
ASP.NET Core Minimal API Example
When using ASP.NET Core Minimal APIs, read the raw request body for signature verification.
Minimal API Webhook Handler
using Felloh;
using Felloh.Errors;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/webhooks/felloh", async (HttpContext context) =>
{
using var reader = new StreamReader(context.Request.Body);
var body = await reader.ReadToEndAsync();
try
{
WebhookVerifier.AssertSignature(
payload: body,
signature: context.Request.Headers["X-Signature"]!,
secret: builder.Configuration["Felloh:WebhookSecret"]!
);
}
catch (FellohWebhookSignatureException)
{
return Results.Unauthorized();
}
var payload = JsonSerializer.Deserialize<JsonElement>(body);
Console.WriteLine($"Webhook received: {payload}");
return Results.Ok();
});
app.Run();
ASP.NET Core MVC Example
When using ASP.NET Core MVC controllers, use Request.Body to read the raw request body.
MVC Controller Webhook Handler
using Felloh;
using Felloh.Errors;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("webhooks")]
public class WebhooksController : ControllerBase
{
private readonly IConfiguration _config;
public WebhooksController(IConfiguration config)
{
_config = config;
}
[HttpPost("felloh")]
public async Task<IActionResult> HandleWebhook()
{
using var reader = new StreamReader(Request.Body);
var body = await reader.ReadToEndAsync();
try
{
WebhookVerifier.AssertSignature(
payload: body,
signature: Request.Headers["X-Signature"]!,
secret: _config["Felloh:WebhookSecret"]!
);
}
catch (FellohWebhookSignatureException)
{
return Unauthorized("Invalid signature");
}
// Process the webhook...
return Ok();
}
}
