Keycloak.AdminClient
1.0.0
See the version list below for details.
dotnet add package Keycloak.AdminClient --version 1.0.0
NuGet\Install-Package Keycloak.AdminClient -Version 1.0.0
<PackageReference Include="Keycloak.AdminClient" Version="1.0.0" />
<PackageVersion Include="Keycloak.AdminClient" Version="1.0.0" />
<PackageReference Include="Keycloak.AdminClient" />
paket add Keycloak.AdminClient --version 1.0.0
#r "nuget: Keycloak.AdminClient, 1.0.0"
#:package Keycloak.AdminClient@1.0.0
#addin nuget:?package=Keycloak.AdminClient&version=1.0.0
#tool nuget:?package=Keycloak.AdminClient&version=1.0.0
Keycloak
A C# library for interacting with a Keycloak authentication server (Keycloak 17+). It provides admin API clients and ASP.NET Core JWT bearer authentication.
Requirements
- .NET Standard 2.0+ (admin API client)
- .NET 8.0+ (JWT bearer authentication extensions)
- Keycloak 17+ (modern URL paths without
/authprefix)
Installation
dotnet add package Keycloak.AdminClient
Or reference the Keycloak project directly from this repository.
Configuration
Recommended: nested Keycloak section
{
"Keycloak": {
"ServerUrl": "https://keycloak.example.com",
"Realm": "myrealm",
"ClientId": "my-service",
"ClientSecret": "your-client-secret",
"ServerSkew": 30,
"ValidateClientId": true
}
}
Legacy flat keys (still supported)
{
"KeycloakServer": "https://keycloak.example.com",
"Realm": "myrealm",
"ClientId": "my-service",
"ClientSecret": "your-client-secret"
}
| Setting | Description |
|---|---|
ServerUrl |
Base Keycloak URL (no trailing /auth) |
Realm |
Realm name |
ClientId / ClientSecret |
Service account for admin API (client credentials) |
ServerSkew |
Clock skew in seconds for token expiry validation |
ValidateClientId |
Whether JWT bearer auth validates the token azp claim |
Dependency injection
using Keycloak.Extensions;
// Program.cs / Startup.cs
builder.Services.AddKeycloak(builder.Configuration);
builder.Services.AddKeycloakAuthentication(); // Requires .NET 8+ app referencing net8.0 build
var app = builder.Build();
app.UseKeycloakAuthentication(); // UseAuthentication + UseAuthorization
AddKeycloak registers:
KeycloakOptionsIKeycloakClientIUserServiceIKeyServiceIRealmService
Usage examples
Create a user
public class MyController
{
private readonly IUserService _users;
public MyController(IUserService users) => _users = users;
public async Task<string> Register(string username, string email)
{
return await _users.CreateUserAsync(new UserRepresentation
{
UserName = username,
EmailAddress = email,
Enabled = true,
});
}
}
Reset a password
await _users.ResetUserPasswordAsync(new CredentialRepresentation
{
Value = "new-password",
Temporary = true,
}, userId);
Send a required-action email
using Keycloak.Constants.Enums;
await _users.SendEmailAsync(userId, new[]
{
RequiredActionsEnum.UpdatePassword,
RequiredActionsEnum.VerifyEmail,
});
Query realm events
var events = await _realmService.GetRealmEventsAsync(new EventQuery
{
Client = "my-app",
FromDate = DateTime.UtcNow.AddDays(-7),
Max = 100,
});
Manual client construction (without DI)
var client = new KeycloakClient(new KeycloakOptions
{
ServerUrl = "https://keycloak.example.com",
Realm = "myrealm",
ClientId = "my-service",
ClientSecret = "secret",
});
var userService = new UserService(client);
Error handling
API failures throw KeycloakApiException with StatusCode, ResponseBody, and RequestUri. Token acquisition failures throw KeycloakAuthenticationException. Configuration problems throw KeycloakConfigurationException.
try
{
await _users.CreateUserAsync(user);
}
catch (KeycloakApiException ex) when (ex.StatusCode == HttpStatusCode.Conflict)
{
// User already exists
}
Breaking changes (recent versions)
If upgrading from an older version of this library:
- URL paths — Keycloak 17+ uses
/realms/...and/admin/realms/...instead of/auth/realms/.... - Static services removed — Use
IUserService,IKeyService,IRealmServicevia DI instead ofUserService.CreateUserAsync(client, ...). - Null on failure removed — Service methods throw
KeycloakApiExceptioninstead of returningnull. HttpResponseMessagereturn types removed — Update/Delete/Email methods returnTaskand throw on failure.IKeycloakClient.Clientremoved —HttpClientis no longer exposed on the interface.- Custom token middleware removed — Use
AddKeycloakAuthentication()andUseKeycloakAuthentication()instead ofUseKeycloakTokenValidation(). - Custom JWT validation helpers removed — Incoming token validation is handled by ASP.NET Core JWT bearer; admin client expiry uses
TokenValidator.IsAccessTokenValid().
Authentication
AddKeycloakAuthentication() configures standard ASP.NET Core JWT bearer authentication using your Keycloak realm authority, ServerSkew, and optional azp validation (ValidateClientId).
It populates HttpContext.User so downstream code can use [Authorize], policies, and User.Identity.
Requires AddKeycloak() to be registered first.
Publishing to NuGet (Trusted Publishing)
Package ID: Keycloak.AdminClient
Publishing uses NuGet Trusted Publishing via the Publish NuGet GitHub Actions workflow.
One-time nuget.org setup
- Sign in to nuget.org as MattUssher (your profile username).
- Open Account → Trusted Publishing → Add policy.
- Use these values exactly:
| Field | Value |
|---|---|
| Policy / package owner | MattUssher (individual account that will own Keycloak.AdminClient) |
| GitHub repository owner | mussher90 |
| GitHub repository | Keycloak |
| Workflow file | publish-nuget.yml |
| Environment | prod |
Important:
- Workflow file is the YAML filename only — not the workflow display name
Publish NuGet. - Environment must match the GitHub Actions environment used by the publish job (
prod). userin the workflow must be the NuGet username of the person who created the policy (MattUssher), not an organization name.- If the repo is private, the policy starts in a 7-day trial. Re-activate it on nuget.org if that window expired before the first successful login.
One-time GitHub setup
- Create an Actions environment named
prod:- GitHub repo → Settings → Environments → New environment → name it
prod
- GitHub repo → Settings → Environments → New environment → name it
- Add a repository secret:
| Secret | Value |
|---|---|
NUGET_USER |
MattUssher |
Do not add a long-lived NUGET_API_KEY when using Trusted Publishing.
Publish
Run Actions → Publish NuGet → Run workflow, or publish a GitHub release.
Testing
dotnet test Keycloak.Test/Keycloak.Test.csproj
License
MIT — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 was computed. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Extensions.Configuration.Abstractions (>= 5.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 5.0.0)
- Microsoft.Extensions.Http (>= 5.0.0)
- Microsoft.Extensions.Options (>= 5.0.0)
- Newtonsoft.Json (>= 13.0.1)
- System.IdentityModel.Tokens.Jwt (>= 7.1.2)
-
net8.0
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 8.0.11)
- Microsoft.Extensions.Configuration.Abstractions (>= 5.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 5.0.0)
- Microsoft.Extensions.Http (>= 5.0.0)
- Microsoft.Extensions.Options (>= 5.0.0)
- Newtonsoft.Json (>= 13.0.1)
- System.IdentityModel.Tokens.Jwt (>= 7.1.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.