MVFC.Aspire.Helpers.Keycloak
9.0.4
dotnet add package MVFC.Aspire.Helpers.Keycloak --version 9.0.4
NuGet\Install-Package MVFC.Aspire.Helpers.Keycloak -Version 9.0.4
<PackageReference Include="MVFC.Aspire.Helpers.Keycloak" Version="9.0.4" />
<PackageVersion Include="MVFC.Aspire.Helpers.Keycloak" Version="9.0.4" />
<PackageReference Include="MVFC.Aspire.Helpers.Keycloak" />
paket add MVFC.Aspire.Helpers.Keycloak --version 9.0.4
#r "nuget: MVFC.Aspire.Helpers.Keycloak, 9.0.4"
#:package MVFC.Aspire.Helpers.Keycloak@9.0.4
#addin nuget:?package=MVFC.Aspire.Helpers.Keycloak&version=9.0.4
#tool nuget:?package=MVFC.Aspire.Helpers.Keycloak&version=9.0.4
MVFC.Aspire.Helpers.Keycloak
This package provides extension methods for .NET Aspire, simplifying the integration, configuration, and initialization of a Keycloak server to manage local environment identity and access.
With it, you can not only initialize an official Keycloak container but also inject configurations (like BaseUrl, Realm, ClientId, etc.) and import custom realms (via JSON seeds) at development time.
Motivation
Keycloak is powerful, but local setup is often painful:
- Large docker commands with many environment variables and import flags.
- Manually importing realms, clients and users from JSON files.
- Repeating the same setup for every project or demo.
With .NET Aspire you can define a Keycloak container, but you still need to:
- Track admin credentials, ports and volumes.
- Decide how to seed realms/clients/users in a repeatable way.
- Make your applications wait for Keycloak to be ready.
MVFC.Aspire.Helpers.Keycloak turns this into a small, opinionated API:
AddKeycloak(...)runs Keycloak with sensible defaults for dev.WithAdminCredentials(...),WithDataVolume(...)andWithSeeds(...)centralize Keycloak‑specific concerns.project.WithReference(keycloak, ...)wires your projects to Keycloak with the correct dependencies and configuration.
Features and Capabilities
- Embedded Server: Starts an official Keycloak container (currently
quay.io/keycloak/keycloak:26.1.1). - Default Authentication: Optional configuration with a pre-defined
ClientIdand seeds for developers. - Customizable Port: Fixed or dynamic port mapping by Aspire.
- Transparent Injection: Adds authentication endpoints to
.WithReference()projects, configuring URLs, realms, and ClientIds as environment variables. - Persistent Volume: Optionally saves state and internal databases.
- Dynamic Realm Import (Seeds): Bootstrap your development environment by populating realms, clients, roles, and users via code configuration.
Installation
Add the package to the main AppHost project in your .NET Aspire solution:
dotnet add package MVFC.Aspire.Helpers.Keycloak
Quick Aspire usage (AppHost)
using Aspire.Hosting;
using MVFC.Aspire.Helpers.Keycloak;
var builder = DistributedApplication.CreateBuilder(args);
// Adding a basic Keycloak container
var keycloak = builder.AddKeycloak("keycloak", port: 9000)
// Example: automatically creating a Realm with clients and roles via code
.WithSeeds(new()
{
Realm = "my-app-realm",
Clients = [
new() { ClientId = "my-api", Secret = "api-secret-1234", DisableAuth = true }
],
Roles = ["Admin", "User"],
Users = [
new() { Username = "admin", Password = "123", Roles = ["Admin", "User"] }
]
});
var api = builder.AddProject<Projects.My_Api>("api")
.WithReference(keycloak, realmName: "my-app-realm", clientId: "my-api", clientSecret: "api-secret-1234")
.WaitFor(keycloak);
builder.Build().Run();
Using the injected configuration in the API
By default, when using .WithReference(keycloak), Aspire injects the following configuration keys into your IConfiguration:
| Configuration Key | Description | Example |
|---|---|---|
Keycloak:BaseUrl |
Full URL to access the Keycloak container. | http://localhost:9000 |
Keycloak:Realm |
Realm name propagated from the AppHost. | my-app-realm |
Keycloak:ClientId |
OAuth/OpenID client ID. | my-api |
Keycloak:ClientSecret |
(Optional) Secret associated with the client. | api-secret-1234 |
Example in your API:
var baseUrl = builder.Configuration["Keycloak:BaseUrl"];
var realm = builder.Configuration["Keycloak:Realm"];
var clientId = builder.Configuration["Keycloak:ClientId"];
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false; // dev
options.Audience = clientId;
options.MetadataAddress = $"{baseUrl}/realms/{realm}/.well-known/openid-configuration";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = $"{baseUrl}/realms/{realm}",
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = clientId
};
});
builder.Services.AddAuthorization();
Provisioning diagram
sequenceDiagram
participant Aspire as .NET Aspire
participant Container as Keycloak Container
participant Configurator as Keycloak Seed Processor
Aspire->>Container: Start container (keycloak)
Container-->>Aspire: Ready (port 8081 available)
Aspire->>Configurator: Trigger OnResourceReady
Configurator->>Container: Authenticate as Admin
Configurator->>Container: Import Realms & Clients
Configurator->>Container: Import Users & Roles
Configurator-->>Aspire: Provisioning Completed
Aspire->>App: Start App
AddKeycloak() options
| Parameter | Type | Description | Default |
|---|---|---|---|
name |
string | Resource name in the Aspire framework. | "keycloak" |
userName |
string | Keycloak master admin user. | admin |
password |
string | Keycloak master admin password. | admin |
port |
int? | Fixed port exposed to localhost (e.g. 9000). If null, Aspire resolves it. | null |
dataBound |
bool | If true, applies .WithDataBindMount() to create a state volume. |
false |
Additional extensions
.WithSeeds(KeycloakRealmSeed)– builds and imports a realm JSON into/opt/keycloak/data/import/..WithRealmImport(importPath)– loads static realm JSONs from a folder and imports into the container.
License
Apache-2.0
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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
- Aspire.Hosting (>= 13.4.6)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 10.0.9)
-
net9.0
- Aspire.Hosting (>= 13.4.6)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 9.0.3)
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 |
|---|---|---|
| 9.0.4 | 89 | 6/26/2026 |
| 9.0.3 | 110 | 4/12/2026 |
| 9.0.2 | 96 | 4/12/2026 |
| 9.0.1 | 99 | 4/12/2026 |
| 9.0.0 | 112 | 4/12/2026 |
| 8.0.2 | 101 | 4/11/2026 |
| 8.0.1 | 115 | 4/3/2026 |
| 8.0.0 | 109 | 4/2/2026 |
| 7.3.3 | 105 | 3/31/2026 |
| 7.3.2 | 105 | 3/30/2026 |
| 7.3.1 | 102 | 3/30/2026 |
| 7.3.0 | 115 | 3/30/2026 |
| 7.2.2 | 117 | 3/29/2026 |
| 7.2.1 | 105 | 3/29/2026 |
| 7.2.0 | 105 | 3/29/2026 |
| 7.1.0 | 101 | 3/22/2026 |
| 6.4.4 | 109 | 3/21/2026 |
| 6.4.3 | 105 | 3/15/2026 |
| 6.4.2 | 102 | 3/15/2026 |
| 6.4.1 | 110 | 3/10/2026 |