Nefarius.Keycloak.Webhooks.FastEndpoints
2.0.0
Prefix Reserved
dotnet add package Nefarius.Keycloak.Webhooks.FastEndpoints --version 2.0.0
NuGet\Install-Package Nefarius.Keycloak.Webhooks.FastEndpoints -Version 2.0.0
<PackageReference Include="Nefarius.Keycloak.Webhooks.FastEndpoints" Version="2.0.0" />
<PackageVersion Include="Nefarius.Keycloak.Webhooks.FastEndpoints" Version="2.0.0" />
<PackageReference Include="Nefarius.Keycloak.Webhooks.FastEndpoints" />
paket add Nefarius.Keycloak.Webhooks.FastEndpoints --version 2.0.0
#r "nuget: Nefarius.Keycloak.Webhooks.FastEndpoints, 2.0.0"
#:package Nefarius.Keycloak.Webhooks.FastEndpoints@2.0.0
#addin nuget:?package=Nefarius.Keycloak.Webhooks.FastEndpoints&version=2.0.0
#tool nuget:?package=Nefarius.Keycloak.Webhooks.FastEndpoints&version=2.0.0
Nefarius.Keycloak.Webhooks
Receive and process Keycloak keycloak-events webhook events as strongly-typed C# objects — no framework lock-in.
About
This repository contains three NuGet packages:
| Package | Purpose |
|---|---|
Nefarius.Keycloak.Webhooks |
Complete payload models, open-ended event parsing and dispatch, HMAC verification, and realm-signed JWT verification. |
Nefarius.Keycloak.Webhooks.FastEndpoints |
HTTP receiver for FastEndpoints with exact-body authentication and event-bus publishing. |
Nefarius.Keycloak.Webhooks.Client |
Typed client for webhook CRUD, secrets, persisted sends/resends, stored payloads, and custom event publishing. |
Features
- Generic user, admin, and custom event models cover every current and future upstream event type.
- Specialized projections remain available for registration, e-mail verification, user CRUD, and realm-role mappings.
- Complete upstream payload preservation, including source
id, deliveryuid, realm name, resource ID, arbitrary details, errors, and raw JSON. KeycloakWebhookParser— static parser,stringandKeycloakWebhookRequestoverloads.KeycloakWebhookDispatcher— specialized and category-level callbacks with no-op defaults.IKeycloakWebhookEventHandler— implement directly if you prefer composition over inheritance.- HMAC-SHA256, legacy HMAC-SHA1, unauthenticated, and realm-signed bearer JWT receiver modes.
- Typed access to every
keycloak-eventsv0.62 webhook and custom-event REST endpoint. - AOT-safe: event dispatch uses statically-resolved generic calls (no reflection).
GenerateDocumentationFileenabled — full XML doc coverage.
Supported frameworks
| Package | Frameworks |
|---|---|
Nefarius.Keycloak.Webhooks |
netstandard2.0, net8.0, net9.0, net10.0 |
Nefarius.Keycloak.Webhooks.FastEndpoints |
net8.0, net9.0, net10.0 |
Nefarius.Keycloak.Webhooks.Client |
netstandard2.0, net8.0, net9.0, net10.0 |
Tested compatibility:
p2-inc/keycloak-eventsv0.62- Keycloak 26.6.3
- Legacy
ext-event-httpuser/admin payloads from the same extension release
Upstream only supports the Keycloak version declared by its release. Other extension or Keycloak versions are not claimed as supported.
Event coverage
access.*becomesUserWebhookEvent.admin.*becomesAdminWebhookEvent.- Application-defined event names become
CustomWebhookEvent. - The existing eight event constants and specialized classes remain available as convenience projections.
- Unknown detail keys and new resource types are preserved; valid events are not silently discarded while returning success.
Limitations
- This repository does not install or replace the Java Keycloak extension.
- Receiver-side deduplication is application-specific and is not persisted by these packages.
- Bearer verification requires access to the configured realm JWKS endpoint.
- Legacy
ext-event-httppayloads do not carry the managed webhook deliveryuid.
Version 2 migration
Keycloak identifiers are opaque strings, not guaranteed UUIDs. Version 2 changes Guid identifier properties to nullable string values and adds category callbacks to IKeycloakWebhookEventHandler. Recompile handlers and remove assumptions that missing IDs equal Guid.Empty.
Installation
Core library (no framework dependency)
dotnet add package Nefarius.Keycloak.Webhooks
FastEndpoints integration
dotnet add package Nefarius.Keycloak.Webhooks.FastEndpoints
Keycloak management client
dotnet add package Nefarius.Keycloak.Webhooks.Client
Usage
With FastEndpoints
Register the integration in your Program.cs before AddFastEndpoints():
using Nefarius.Keycloak.Webhooks.Authentication;
using Nefarius.Keycloak.Webhooks.FastEndpoints;
// Register options (optional — customise route and auth below)
builder.Services.AddKeycloakWebhooks(options =>
{
options.Route = "/api/webhooks/{Id}";
options.AuthenticationMode = KeycloakWebhookAuthenticationMode.HmacSha256;
options.HmacSecret = builder.Configuration["Keycloak:WebhookSecret"];
});
builder.Services.AddFastEndpoints();
For realm-signed bearer authentication:
builder.Services.AddKeycloakWebhooks(options =>
{
options.AuthenticationMode = KeycloakWebhookAuthenticationMode.Bearer;
options.Jwt.Issuer = "https://id.example/realms/acme";
options.Jwt.Audience = "https://receiver.example/api/webhooks/keycloak";
});
The endpoint validates the realm signing key from the issuer JWKS, issuer, audience, expiry, jti, and request_body_sha256. JWKS endpoints must use HTTPS, except loopback addresses used in tests.
AuthenticationMode.None is available for explicitly unauthenticated webhooks. Do not use it on an Internet-facing endpoint without equivalent network controls.
Then implement a FastEndpoints IEventHandler<T> for each event type you care about:
using FastEndpoints;
using Nefarius.Keycloak.Webhooks.Events;
public class UserRegisteredHandler : IEventHandler<AccessUserRegisteredEvent>
{
public Task HandleAsync(AccessUserRegisteredEvent evt, CancellationToken ct)
{
Console.WriteLine($"New user registered: {evt.Email}");
return Task.CompletedTask;
}
}
Without FastEndpoints (framework-agnostic)
Extend KeycloakWebhookDispatcher and override only the events you need, then call DispatchAsync:
using Nefarius.Keycloak.Webhooks;
using Nefarius.Keycloak.Webhooks.Events;
public class MyWebhookHandler : KeycloakWebhookDispatcher
{
public override Task OnAccessUserRegisteredAsync(AccessUserRegisteredEvent evt, CancellationToken ct = default)
{
Console.WriteLine($"Registered: {evt.Email}");
return Task.CompletedTask;
}
}
// Somewhere in your HTTP handler:
var handler = new MyWebhookHandler();
await handler.DispatchAsync(requestBodyJson, cancellationToken);
Alternatively, parse manually with KeycloakWebhookParser:
using Nefarius.Keycloak.Webhooks;
using Nefarius.Keycloak.Webhooks.Events;
WebhookBaseEvent? evt = KeycloakWebhookParser.Parse(requestBodyJson);
if (evt is AccessUserRegisteredEvent reg)
{
// handle registration
}
Management client
Configure the HttpClient with a Keycloak access token that has view-events, manage-events, or publish-events as required:
using System.Net.Http.Headers;
using Nefarius.Keycloak.Webhooks.Client;
var http = new HttpClient
{
BaseAddress = new Uri("https://id.example/") // may include a relative path such as /auth/
};
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
var client = new KeycloakWebhooksClient(http);
var webhooks = await client.GetWebhooksAsync("acme");
The client covers webhook list/count/create/get/update/delete, secret retrieval, send history, send detail/resend, stored payload lookup, sends by source event, and custom event publishing.
Delivery semantics
- Keycloak treats every 2xx response as delivered and retries non-2xx responses.
- The FastEndpoints receiver returns 2xx only after authentication, parsing, and event handlers succeed.
- Keycloak can deliver the same event more than once. Make handlers idempotent using delivery
uidor source eventid, depending on the required scope. - HMAC and JWT body-hash checks use the exact request bytes. Do not deserialize and reserialize before verification.
Build
Prerequisites:
- .NET SDK 10.0 or later
git clone https://github.com/nefarius/Nefarius.Keycloak.Webhooks.git
cd Nefarius.Keycloak.Webhooks
dotnet restore
dotnet test -c Release
dotnet pack -c Release --no-restore
Packages land in bin/ at the repo root (configured in Directory.Build.props).
API Documentation
Auto-generated API docs are published to /docs on every push to master.
Support
This is a community library, not a commercial product.
- Search existing issues before opening a new one.
- The issue tracker is not a support forum. For general questions, use GitHub Discussions.
- No SLA or guaranteed response time.
License
MIT — see LICENSE.
Keycloak is a trademark of Red Hat, Inc. This project is independent and is not affiliated with or endorsed by Red Hat or Phase Two.
Sources & Credits
- p2-inc/keycloak-events v0.62 — the Elastic License 2.0 Keycloak extension whose external protocol and REST resources this library implements.
- FastEndpoints — HTTP framework used by the optional integration package.
- Microsoft.IdentityModel.JsonWebTokens — JWT signature and claims validation.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- FastEndpoints (>= 8.2.0)
- Microsoft.Extensions.Http (>= 8.0.1)
- Nefarius.Keycloak.Webhooks (>= 2.0.0)
-
net8.0
- FastEndpoints (>= 8.2.0)
- Microsoft.Extensions.Http (>= 8.0.1)
- Nefarius.Keycloak.Webhooks (>= 2.0.0)
-
net9.0
- FastEndpoints (>= 8.2.0)
- Microsoft.Extensions.Http (>= 8.0.1)
- Nefarius.Keycloak.Webhooks (>= 2.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0 | 131 | 7/14/2026 |
| 2.0.0-pre001 | 118 | 7/14/2026 |
| 1.0.1 | 124 | 6/23/2026 |
| 1.0.0 | 124 | 6/23/2026 |
| 1.0.0-pre001 | 117 | 6/23/2026 |