Keycloak.AuthServices, a Keycloak client library for ASP.NET Core
Authentication and Authorization with Keycloak and ASP.NET Core ๐
At a glance
- What is it?
- Keycloak.AuthServices is a set of NuGet packages that wire Keycloak into ASP.NET Core as both an OIDC login provider and an authorization server, with add-on packages for token introspection, UMA 2.0 and the admin API. It removes configuration boilerplate, and it ties your app to one identity provider's way of doing things.
- Who is it for?
- Keycloak.AuthServices suits teams that have already decided on Keycloak as their identity provider and want role and realm-role policies in ASP.NET Core without hand-writing the authentication wiring or the admin API calls.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 144 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Nine packages, one identity provider
Keycloak.AuthServices is not a framework and not a server. It is a family of NuGet packages that sit inside an ASP.NET Core application and handle the parts of talking to Keycloak that every project ends up rewriting: validating tokens, mapping roles onto authorization policies, calling the admin API, and exchanging tokens for the fancier flows. The package table in the project documentation makes the shape of it clear.
The two core packages are `Keycloak.AuthServices.Authentication`, described as Keycloak authentication with JWT and OIDC, and `Keycloak.AuthServices.Authorization`, for using Keycloak as an authorization server. Around those sit focused add-ons: `Keycloak.AuthServices.Authorization.TokenIntrospection` for lightweight access tokens with a note that it needs Keycloak 24 or later, `Keycloak.AuthServices.Authorization.Uma` for UMA 2.0 with permission ticket challenges and RPT exchange, `Keycloak.AuthServices.Sdk` and `Keycloak.AuthServices.Sdk.Kiota` for HTTP API integration with Keycloak, the latter based on OpenAPI, `Keycloak.AuthServices.OpenTelemetry` for tracing, and `Keycloak.AuthServices.Templates` for `dotnet new` templates.
That split matters for how you adopt it. Nobody installs all nine. Most teams take Authentication, add Authorization when they need centralized policies, and reach for the Sdk packages only when the application itself administers realms, clients or users. The Templates package is worth knowing about because the repository ships a long list of runnable samples under samples/, including GettingStarted, Blazor, ClientSecretJwt, TokenIntrospection, UmaResourceSharing, OrganizationAuthorization and ResourceAuthorization, which is where the real usage patterns live.
Authentication is three lines of service registration
The getting-started path is short because the package hides the boilerplate. You add the package to the project.
dotnet add package Keycloak.AuthServices.AuthenticationThen the Program.cs of a minimal API registers authentication and authorization and protects a single endpoint.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKeycloakWebApiAuthentication(builder.Configuration);
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/", () => "Hello World!").RequireAuthorization();
app.Run();Two details deserve attention. First, the call takes `builder.Configuration`, so the Keycloak connection details are read from configuration rather than from code, which is what makes the same binary usable across environments. Second, `UseAuthentication()` and `UseAuthorization()` still have to be in the pipeline in that order, and the endpoint still needs `RequireAuthorization()`. The package does not remove ASP.NET Core's own model; it plugs into it.
The configuration shape follows the Keycloak client registration, so an existing Keycloak client can be described directly.
//appsettings.json
{
"Keycloak": {
"realm": "Test",
"auth-server-url": "http://localhost:8080/",
"ssl-required": "none",
"resource": "test-client",
"verify-token-audience": false,
"credentials": {
"secret": ""
},
"confidential-port": 0
}
}Read that as a description of the client, not of the server: realm names the realm, auth-server-url points at the server, resource names the client, credentials holds the client secret, and `ssl-required` set to none plus a local `http://localhost:8080/` URL is development configuration. The documentation does not show a production variant of this file, so how to store a real client secret in production, whether through environment variables, a secret store or a user secrets setting, is a decision your deployment has to make.
Realm roles and resource roles become one policy
The Authorization package is where the library earns its keep, and the mechanism it exposes is policy based. The documentation describes it as allowing you to define policies based on roles and to use Keycloak as an authorization server so that authorization policies can be organized and applied centrally.
The sample defines a policy that requires two different kinds of role at once.
services.AddAuthorization(options =>
{
options.AddPolicy("AdminAndUser", builder =>
{
builder
.RequireRealmRoles("User") // Realm role is fetched from token
.RequireResourceRoles("Admin"); // Resource/Client role is fetched from token
});
})
.AddKeycloakAuthorization(configuration);The inline comments are worth pausing on because they carry the whole design. A realm role is fetched from the token, and a resource role, which in Keycloak terms is a client role, is fetched from the token as well. The distinction is that realm roles are global within the realm while resource roles belong to one client. So `RequireRealmRoles("User")` says the caller must hold a realm-wide role, `RequireResourceRoles("Admin")` says the caller must hold a role attached to the client that issued the token.
That gives you two axes of authorization in one policy expression, and it explains why the sample name is AdminAndUser: the policy is satisfied only when both conditions hold. The endpoint then references it by name.
app.MapGet("/hello", () => "[]")
.RequireAuthorization("AdminAndUser");The alternative to this model is putting the role logic in the identity provider and having the application check a single scope or a single client role. The trade-off is real: policy-based authorization in your code is testable and visible in the repository, but it also means the same rules exist in two places, in Keycloak and in your policy definitions, and a role renamed in Keycloak breaks the policy silently until someone hits the endpoint.
The admin API client builds a service collection by hand
Beyond authentication and authorization, the SDK packages give you a typed client for Keycloak's HTTP API, so an application can administer realms instead of only consuming tokens. The sample shows it used outside the normal web host, by constructing a service collection directly.
var services = new ServiceCollection();
services.AddKeycloakAdminHttpClient(new KeycloakAdminClientOptions
{
AuthServerUrl = "http://localhost:8080/",
Realm = "master",
Resource = "admin-api",
});
var sp = services.BuildServiceProvider();
var client = sp.GetRequiredService<IKeycloakRealmClient>();
var realm = await client.GetRealmAsync("Test");Three things to note. The options type names the server, the realm and the resource separately, and here the resource is `admin-api` rather than the `test-client` of the web sample, because an admin client is a different kind of Keycloak client with different permissions. The realm is `master`, the administrative realm, while the call itself asks for the realm named `Test`. And the resolver asked for is `IKeycloakRealmClient`, a realm-level interface, which suggests the SDK is split along the lines of Keycloak's own API surface rather than being one wide client.
Building the provider by hand is fine for a script, a background worker or a test, but it is not how you would wire this into a web application, where the same registration would normally go through the application's own service collection. The documentation does not show how credentials are supplied to this admin client in the sample, so where the admin client secret comes from is something you need to determine from the API reference, which is published separately from the developer documentation.
Two SDK variants exist, plain `Keycloak.AuthServices.Sdk` and `Keycloak.AuthServices.Sdk.Kiota`, the latter described as based on OpenAPI. That duplication suggests a generated client alongside a hand-written one, and the choice between them is worth a look in the API reference before you commit to either.
Introspection and UMA cover the flows plain JWT cannot
The two more specialized packages exist because a self-contained JWT cannot express everything a Keycloak deployment does. The TokenIntrospection package is described as token introspection for lightweight access tokens, and the table notes a Keycloak 24 or later requirement. The idea is that instead of shipping a fat signed token to every API, you hand the token to Keycloak and ask the server what it actually means, which keeps the token small and moves the decision to the authority.
The cost of that model is a network round trip on every authorization decision, plus a hard dependency on a Keycloak version. If Keycloak is unreachable, requests that depend on introspection fail, which is a different availability profile from local JWT validation. The documentation does not describe any caching layer or fallback, so that failure mode is worth checking against your requirements before you adopt it.
The Uma package covers UMA 2.0, specifically permission ticket challenges and RPT exchange. UMA is the model where a resource server asks the authorization server for permission to act on behalf of a user, receives a ticket to present for a decision, and exchanges it for a requesting party token. That is the flow you need when access decisions are made by the client application rather than by the user, and it is exactly the flow that cannot be expressed as a static role check in a policy.
Both packages add real complexity, and neither is in the basic getting-started path. The repository samples directory confirms that they are treated as separate scenarios with dedicated examples, TokenIntrospection and UmaResourceSharing, rather than as small extensions to the main sample.
Version 3.0.0 shipped in May 2026, the last push was in June
The release record shows 3.0.0 tagged on 2026-05-02, preceded by 3.0.0-rc.1 in April 2026 and 2.10.0-rc.1 in the same month. A major version bump with release candidates beforehand is the shape of a deliberate breaking change rather than an accident, so if you are on a 2.x package, expect to read the migration notes before moving.
The last push to the repository was on 2026-06-02, and the project is not archived, but there is no activity in the repository after that date, and the documentation does not describe a support policy for the 2.x line. For a library sitting in the authentication path of a production application, that question matters more than it would for a utility: a breaking change in token validation or policy registration is a deployment event, not a pull request.
The licence is MIT, which is the easy case. You can use the packages in commercial and closed-source products, redistribute them, and modify them, with the copyright notice and licence text carried along. No copyleft obligations attach to applications that merely reference the packages, and there is no separate commercial tier implied by the split into several packages.
One maintenance detail is not about Keycloak at all. The repository is built with Cake, and the documentation lists the developer commands as `dotnet cake --target build`, `dotnet cake --target test` and `dotnet pack -o ./Artefacts`. The build also carries a husky setup and an editorconfig, so contribution hooks run locally, and the package itself is published to NuGet under the Keycloak.AuthServices prefix.
When a different approach is the better one
The honest alternative to this library is not another Keycloak package, it is writing the integration yourself, because the value here is mostly the wiring that everyone writes anyway. ASP.NET Core can validate OIDC tokens without this library by pointing a JWT bearer setup at the Keycloak realm URL, and it can enforce role checks with plain authorization policies. That path gives you fewer packages and full control over the authentication pipeline, at the cost of the configuration and the boilerplate the library provides.
Inside the Keycloak ecosystem, the other choice is a single heavyweight client rather than nine small ones. A monolith package that bundles authentication, admin API, UMA and introspection pulls in the whole Keycloak surface in your application whether you use it or not, and it makes the Keycloak version requirement of one feature the constraint of all features. The split design here means the TokenIntrospection package's Keycloak 24 requirement stays optional, and a team that never calls the admin API never references the SDK.
The real boundary is different though. This library makes Keycloak the center of your identity model. If your organization standardizes on another identity provider, the roles and policies here will not map onto it, and the value of the package drops to the level of the generic OIDC wiring that the framework already offers. The scenarios directory in the repository, including OrganizationAuthorization and ResourceAuthorization, points the same way: the library is at its best when Keycloak is not up for negotiation.
There is also a middle option worth naming. If all you need is to create a client, a realm or a user in Keycloak from a deployment script, the admin client is enough, and pulling in the authentication and authorization packages for that is more than the job requires.
Editorial conclusion
Keycloak.AuthServices suits teams that have already decided on Keycloak as their identity provider and want role and realm-role policies in ASP.NET Core without hand-writing the authentication wiring or the admin API calls. It does not suit a team that wants provider-agnostic code, a team that has not settled on an identity provider yet, or a team that needs behaviour the packages do not cover, such as UMA workflows or token introspection without accepting the Keycloak 24 or later requirement that the documentation attaches to them. Verify first that the package version you take matches your Keycloak server version, that the realm, client and role names in your configuration match what your Keycloak administrator actually created, and that the policy model you plan to use, realm roles for coarse access and resource roles for client-level access, fits how your client applications are registered.
Frequently asked questions
Which NuGet package do I need to add Keycloak authentication to an ASP.NET Core project?
The documentation shows adding Keycloak.AuthServices.Authentication with dotnet add package, then calling AddKeycloakWebApiAuthentication on the service collection with the configuration. The Authorization package is separate and adds role based policies.
What is the difference between a realm role and a resource role in Keycloak.AuthServices?
Both are read from the token, as the sample comments state. A realm role applies across the realm, while a resource role, which is a client role in Keycloak terms, belongs to the client that issued the token, and a policy can require both at once.
Does Keycloak.AuthServices support UMA 2.0 and token introspection?
Yes, through separate packages. Keycloak.AuthServices.Authorization.Uma covers UMA 2.0 with permission ticket challenges and RPT exchange, and Keycloak.AuthServices.Authorization.TokenIntrospection covers introspection for lightweight access tokens with a stated Keycloak 24 or later requirement.
How do I call the Keycloak admin API from .NET?
The SDK package exposes a typed client registered with AddKeycloakAdminHttpClient and a KeycloakAdminClientOptions object holding AuthServerUrl, Realm and Resource, after which IKeycloakRealmClient can be resolved and used, for example with GetRealmAsync.
What licence does Keycloak.AuthServices use?
The project is licensed under MIT, so the packages can be used in commercial and closed-source applications provided the copyright notice and licence text are kept with them. The licence file in the repository is LICENSE.md.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nikiforovall-keycloak-authorization-services-dotnet)Was this useful?