### Quick Start: Keycloak Organization Authorization Setup Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/samples/OrganizationAuthorization/README.md Steps to start Keycloak, seed organizations and members, obtain a bearer token, and run the sample application. ```bash # 1. Start Keycloak docker compose up -d # 2. Seed organizations and assign members (waits for KC to be ready) bash ./assets/seed.sh # 3. Get a bearer token and save to .env bash ./assets/get-token.sh > .env # 4. Run the sample dotnet run ``` -------------------------------- ### Run UMA Resource Sharing Example Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/examples/uma-resource-sharing.md Command to run the UMA resource sharing example using .NET Aspire. This command starts the application host, which in turn launches the client and resource server applications. ```bash dotnet run --project samples/UmaResourceSharing/AppHost ``` -------------------------------- ### Install Keycloak.AuthServices Plugin from GitHub Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/README-plugin.md Steps to add the marketplace and install the plugin from GitHub. ```bash # 1. Add the marketplace /plugin marketplace add NikiforovAll/keycloak-authorization-services-dotnet # 2. Install the plugin /plugin install keycloak-authservices@keycloak-authservices ``` -------------------------------- ### Keycloak Production Mode Setup Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-administration/SKILL.md Build and start Keycloak in production mode with PostgreSQL database configuration. This involves building the server, setting environment variables for the database and hostname, and then starting the optimized server. ```bash bin/kc.sh build --db=postgres export KC_DB=postgres export KC_DB_URL=jdbc:postgresql://localhost/keycloak export KC_DB_USERNAME=keycloak export KC_DB_PASSWORD=password export KC_HOSTNAME=keycloak.example.com bin/kc.sh start --optimized ``` -------------------------------- ### Install Keycloak.AuthServices.Sdk Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/admin-rest-api/admin-rest-api.md Install the Keycloak.AuthServices.Sdk NuGet package using the .NET CLI. ```bash dotnet add package Keycloak.AuthServices.Sdk ``` -------------------------------- ### Install Keycloak.AuthServices.Aspire.Hosting Package Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/devex/aspire.md Install the necessary NuGet package to your AppHost project. ```bash dotnet add package Keycloak.AuthServices.Aspire.Hosting ``` -------------------------------- ### Install Template from Source Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/src/Keycloak.AuthServices.Templates/README.md Installs the Keycloak.AuthServices.Templates from a local source directory. ```bash dotnet new install . ``` -------------------------------- ### Run the Sample Application Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/samples/OAuthServerMetadata/README.md Executes the sample .NET application after setup. ```bash # 4. Run the sample dotnet run ``` -------------------------------- ### Basic ASP.NET Core App Setup with Authorization Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/authorization/resources-api.md Demonstrates the minimal setup for an ASP.NET Core application to use authentication and authorization, including mapping an endpoint that requires authorization. ```csharp var app = builder.Build(); app.UseAuthentication(); app.UseAuthorization(); app.MapGet("/", () => "Hello World!") .RequireAuthorization(policyName); app.Run(); ``` -------------------------------- ### Install Keycloak.AuthServices Plugin from Local Path Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/README-plugin.md Steps to install the plugin from a local directory for development purposes. ```bash # Add local directory as marketplace /plugin marketplace add ./path/to/keycloak-authorization-services-dotnet # Install /plugin install keycloak-authservices@keycloak-authservices ``` -------------------------------- ### AppHost Setup with Keycloak Container Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/devex.md Configures the AppHost to start a Keycloak Docker container and reference it for service discovery and environment variables. ```csharp // AppHost/Program.cs var builder = DistributedApplication.CreateBuilder(args); var keycloak = builder.AddKeycloakContainer("keycloak"); var realm = keycloak.AddRealm("Test"); builder.AddProject("api") .WithReference(keycloak) .WithReference(realm); builder.Build().Run(); ``` -------------------------------- ### Install Template by Name Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/src/Keycloak.AuthServices.Templates/README.md Installs the Keycloak.AuthServices.Templates using its NuGet package name. ```bash dotnet new install Keycloak.AuthServices.Templates ``` -------------------------------- ### Quick Start: Docker and .NET CLI Commands Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/samples/ClientSecretJwt/README.md Commands to start Keycloak using Docker Compose and run the .NET sample application. A brief wait is included for Keycloak to initialize. ```bash # 1. Start Keycloak with the pre-configured Test realm docker compose up -d # 2. Run the sample (waits ~10s for Keycloak to be ready) dotnet run ``` -------------------------------- ### Keycloak Realm Client Test Example Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/admin-rest-api/access-token.md An example demonstrating how to get a realm asynchronously. This snippet is part of integration tests for Keycloak Realm Client. ```csharp var realm = await _keycloakRealmClient.GetRealmAsync("master"); Assert.NotNull(realm); Assert.Equal("master", realm.RealmName); Assert.True(realm.Enabled); var realm2 = await _keycloakRealmClient.GetRealmAsync("non-existent-realm"); Assert.Null(realm2); ``` -------------------------------- ### Keycloak Authorization Metrics Example Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/devex.md Example output showing counts for successful and failed authorization requirements. ```text [Keycloak.AuthServices.Authorization] keycloak.authservices.requirements.fail (Count) requirement=ParameterizedProtectedResourceRequirement 3 keycloak.authservices.requirements.succeed (Count) requirement=ParameterizedProtectedResourceRequirement 5 requirement=RealmAccessRequirement 16 ``` -------------------------------- ### Example Keycloak.json Adapter File Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/configuration/configuration-authentication.md Provides an example structure for the 'keycloak.json' adapter configuration file. This file contains essential settings for connecting to a Keycloak server. ```json { "realm": "Test", "auth-server-url": "http://localhost:8088/", "ssl-required": "external", "resource": "test-client", "verify-token-audience": true } ``` -------------------------------- ### Start Keycloak with Docker Compose Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/samples/WebApp/README.md Starts Keycloak, a realm, a client, and test users using Docker Compose. Ensure Docker is running. ```bash docker compose up -d ``` -------------------------------- ### Install Keycloak.AuthServices.Templates Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/devex/aspire.md Install the Keycloak.AuthServices.Templates NuGet package to scaffold new Aspire projects with pre-configured Keycloak integration. ```bash dotnet new install Keycloak.AuthServices.Templates ``` -------------------------------- ### Main Program Setup for Authorization Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/examples/authorization-getting-started.md The main program setup for a .NET application demonstrating Keycloak authorization. It configures the web host and registers authorization services. ```csharp using Keycloak.AuthServices.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; var builder = WebApplication.CreateBuilder(args); builder.Services.AddKeycloakAuthorization(options => { options.Realm = builder.Configuration["Keycloak:realm"]; options.AuthServerUrl = builder.Configuration["Keycloak:AuthServerUrl"]; options.Resource = builder.Configuration["Keycloak:resource"]; }); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthorization(); app.MapGet("/", () => "Hello World!").RequireAuthorization(); app.Run(); ``` -------------------------------- ### Install Keycloak Authorization Services Plugin Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/ai/skills.md Install the keycloak-authservices plugin from the specified marketplace. This makes the skills available for use. ```bash # Install the plugin /plugin install keycloak-authservices@NikiforovAll-keycloak-authorization-services-dotnet ``` -------------------------------- ### Get Users using IKeycloakUserClient (Hand-Written SDK) Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/admin-sdk.md Example of retrieving a list of users from a specific Keycloak realm using the IKeycloakUserClient interface. ```csharp app.MapGet("/users", async (IKeycloakUserClient client) => await client.GetUsers("my-realm")); ``` -------------------------------- ### Run Aspire Web API Sample Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/examples/aspire-web-api.md Execute the Aspire project to start the Keycloak instance and Web API. This command initiates the sample application. ```bash dotnet run --project ./AppHost ``` -------------------------------- ### Basic Organization Authorization Setup Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/examples/organization-authorization.md Sets up the Keycloak authorization services with basic configuration for organization-based access control. This snippet demonstrates the initial setup required in the Program.cs file. ```csharp using Keycloak.AuthServices.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddAuthorization(); builder.Services.AddKeycloakAuthorization( builder.Configuration.GetSection("Keycloak")); var app = builder.Build(); // Configure the HTTP request pipeline. app.UseHttpsRedirection(); app.UseAuthorization(); app.MapGet("/", () => "Hello World!") .RequireAuthorization(); app.Run(); ``` -------------------------------- ### Setup Dependency Injection Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/examples/resource-authorization.md Configure the dependency injection container for resource authorization services. ```csharp using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // Add Keycloak authorization services builder.Services.AddKeycloakAuthorization( builder.Configuration.GetSection("Keycloak")); // Add workspace services builder.Services.AddSingleton(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); // Use Keycloak authorization middleware app.UseKeycloakAuthorization(); app.MapControllers(); app.Run(); ``` -------------------------------- ### Add Marketplace Plugin Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/ai/skills.md Add the marketplace to install plugins. This is a prerequisite for installing specific plugins. ```bash # Add the marketplace /plugin marketplace add NikiforovAll/keycloak-authorization-services-dotnet ``` -------------------------------- ### List Installed Keycloak Templates Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/devex/templates.md Lists all installed templates related to 'keycloak' to show available project types. ```bash ❯ dotnet new list keycloak # These templates matched your input: 'keycloak' # Template Name Short Name Language Tags # ----------------------- ----------------------- -------- ------------------------------------- # Keycloak Aspire Starter keycloak-aspire-starter [C#] Common/.NET Aspire/Cloud/API/Keycloak # Keycloak WebApi keycloak-webapi [C#] Common/API/Keycloak ``` -------------------------------- ### Verify Keycloak.AuthServices Plugin Installation Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/README-plugin.md Commands to run after installation to make skills available. Requires a plugin reload. ```bash /reload-plugins /keycloak-authservices:keycloak-administration /keycloak-authservices:keycloak-auth-services ``` -------------------------------- ### Hand-Written SDK Usage Example Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/admin-sdk.md Demonstrates how to inject and use the Keycloak Admin SDK clients in an application to perform common operations. ```APIDOC ## Hand-Written SDK Usage Example ### Description Examples of injecting and using `IKeycloakUserClient` and `IKeycloakRealmClient` to fetch user and realm data. ### Method Dependency Injection of `IKeycloakUserClient` or `IKeycloakRealmClient`. ### Usage Example ```csharp // Fetching users for a realm app.MapGet("/users", async (IKeycloakUserClient client) => await client.GetUsers("my-realm")); // Fetching a specific realm app.MapGet("/realm", async (IKeycloakRealmClient client) => await client.GetRealmAsync("my-realm")); ``` ``` -------------------------------- ### Start Keycloak and Verify Metadata Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/samples/OAuthServerMetadata/README.md Starts Keycloak using Docker Compose and verifies both OIDC and RFC 8414 discovery endpoints. ```bash # 1. Start Keycloak docker compose up -d # 2. Wait for Keycloak to be ready, then verify both discovery endpoints bash ./assets/verify-metadata.sh ``` -------------------------------- ### Install Keycloak Authentication Package Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/getting-started.md Add the Keycloak.AuthServices.Authentication NuGet package to your project using the dotnet CLI. ```bash dotnet add package Keycloak.AuthServices.Authentication ``` -------------------------------- ### Keycloak Configuration Example in keycloak.json Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/authentication.md Example of a standalone 'keycloak.json' file used for configuring Keycloak settings. This file specifies realm, authentication server URL, SSL requirements, resource, and token audience verification. ```json // keycloak.json { "realm": "Test", "auth-server-url": "http://localhost:8088/", "ssl-required": "external", "resource": "test-client", "verify-token-audience": true } ``` -------------------------------- ### Install Duende.AccessTokenManagement Package Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/admin-rest-api/access-token.md Command to install the Duende.AccessTokenManagement NuGet package using the .NET CLI. This library helps in retrieving and caching access tokens. ```bash dotnet add package Duende.AccessTokenManagement ``` -------------------------------- ### Blazor Client and Resource Server Setup Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/examples/uma-resource-sharing.md Illustrates a two-project setup where a Blazor Server client communicates with a separate Minimal API resource server. The UmaTokenHandler facilitates transparent UMA challenge-response between the client and server. ```csharp <<< @/../samples/UmaResourceSharing/ResourceServer/Program.cs ``` ```csharp <<< @/../samples/UmaResourceSharing/ClientApp/Program.cs ``` -------------------------------- ### Configure Keycloak Configuration Source from Adapter File Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/configuration.md Example of configuring the Keycloak configuration source using a standalone 'keycloak.json' file instead of appsettings.json. ```csharp builder.Host.ConfigureKeycloakConfigurationSource("keycloak.json"); ``` -------------------------------- ### Quick Test Keycloak.AuthServices Plugin (Development) Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/README-plugin.md Load the plugin directly without installation for quick testing during development. ```bash # Load plugin directly without installation claude --plugin-dir ./path/to/keycloak-authorization-services-dotnet ``` -------------------------------- ### Add Keycloak.AuthServices.OpenTelemetry Package Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/opentelemetry.md Install the OpenTelemetry package for Keycloak.AuthServices using the .NET CLI. ```bash dotnet add package Keycloak.AuthServices.OpenTelemetry ``` -------------------------------- ### Resource Server Setup for UMA and Keycloak Authorization Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/samples/UmaResourceSharing/ClientApp/README.md Configure .NET services to enable Keycloak authorization, UMA challenge handling, and resilience. This setup is crucial for protecting endpoints and managing permission tickets. ```csharp // Keycloak authorization + UMA challenge handler services .AddAuthorization() .AddKeycloakAuthorization() .AddUmaPermissionTicketChallenge(); services.AddAuthorizationServer(configuration).AddStandardResilienceHandler(); // Protection API client — for permission ticket management and UMA challenges services.AddKeycloakProtectionHttpClient(configuration) .AddClientCredentialsTokenHandler(tokenClientName); // Protected endpoints — scopes enforced via Keycloak authorization server app.MapGet("/documents/{name}", ...) .RequireProtectedResource("shared-document", "read"); // Permission ticket management endpoints app.MapGet("/permissions/pending", ...) // List pending tickets app.MapPut("/permissions/{id}/approve", ...) // Approve a ticket app.MapDelete("/permissions/{id}", ...) // Deny/delete a ticket ``` -------------------------------- ### Run the .NET Application Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/getting-started.md Execute the dotnet run command to start your secured Web API. Observe the output for listening addresses and application status. ```bash dotnet run # Building... # info: Microsoft.Hosting.Lifetime[14] # Now listening on: http://localhost:5228 # info: Microsoft.Hosting.Lifetime[0] # Application started. Press Ctrl+C to shut down. # info: Microsoft.Hosting.Lifetime[0] # Hosting environment: Development # info: Microsoft.Hosting.Lifetime[0] # Content root path: C:\Users\Oleksii_Nikiforov\dev\keycloak-authorization-services-dotnet\samples\GettingStarted ``` -------------------------------- ### Require Resource Roles Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/configuration/configuration-authorization.md Example demonstrating how to require specific resource roles for authorization. ```csharp using Keycloak.AuthServices.Authorization; // ... var builder = WebApplication.CreateBuilder(args); builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { options.Authority = "http://localhost:8080/realms/myrealm"; options.Audience = "my-client"; options.RequireHttpsMetadata = false; }); builder.Services.AddAuthorization(options => { options.AddPolicy("TestClientRole", policy => policy.RequireClientRoles("test-client-role")); }); var app = builder.Build(); app.UseAuthentication(); app.UseAuthorization(); app.MapGet("/", () => "Hello World!").RequireAuthorization("TestClientRole"); app.Run(); ``` -------------------------------- ### Run .NET Project with Aspire Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/samples/UmaResourceSharing/README.md Starts the .NET application using Aspire orchestration. The Aspire dashboard will open automatically. ```bash dotnet run --project AppHost ``` -------------------------------- ### Start Keycloak and Seed Configuration Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/samples/TokenIntrospection/README.md These bash scripts are used to start the Keycloak Docker container, configure the client to issue lightweight tokens by disabling role mappers in the access token, and obtain a bearer token. ```bash # 1. Start Keycloak docker compose up -d # 2. Seed: configure client to issue lightweight tokens (disables role mappers in access token) bash ./assets/seed.sh # 3. Get a bearer token and save to .env bash ./assets/get-token.sh > .env # 4. Run the sample dotnet run ``` -------------------------------- ### Kiota-Generated Client Usage Example Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/admin-sdk.md Shows how to obtain and use the Kiota-generated `KeycloakAdminApiClient` to interact with Keycloak resources. ```APIDOC ## Kiota-Generated Client Usage Example ### Description Demonstrates obtaining the `KeycloakAdminApiClient` and using its fluent interface to access realm and user data. ### Method Dependency Injection of `KeycloakAdminApiClient`. ### Usage Example ```csharp // Assuming 'sp' is a ServiceProvider var client = sp.GetRequiredService(); // Get a specific realm var realm = await client.Admin.Realms["Test"].GetAsync(); // Get all users in a realm var users = await client.Admin.Realms["Test"].Users.GetAsync(); ``` ``` -------------------------------- ### Require Realm Roles Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/configuration/configuration-authorization.md Example demonstrating how to require specific realm roles for authorization. ```csharp using Keycloak.AuthServices.Authorization; // ... var builder = WebApplication.CreateBuilder(args); builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { options.Authority = "http://localhost:8080/realms/myrealm"; options.Audience = "my-client"; options.RequireHttpsMetadata = false; }); builder.Services.AddAuthorization(options => { options.AddPolicy("AdminOnly", policy => policy.RequireRealmRoles("admin")); }); var app = builder.Build(); app.UseAuthentication(); app.UseAuthorization(); app.MapGet("/", () => "Hello World!").RequireAuthorization("AdminOnly"); app.Run(); ``` -------------------------------- ### Run the Aspire Application Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/src/Keycloak.AuthServices.Templates/AspireStarterTemplate/README.md Command to run the Aspire application host, which starts the Keycloak container and the defined projects. ```csharp dotnet run --project ./AppHost/ ``` -------------------------------- ### Run Keycloak Docker Image Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/getting-started.md Start a local Keycloak instance using Docker. This is necessary for Keycloak to handle authentication requests from your API. ```bash docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:26.4.2 start-dev ``` -------------------------------- ### Add UMA Packages for Resource Server Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/protection-api/uma.md Install the necessary packages for a separate resource server pattern. This includes core authorization and UMA challenge handling. ```bash dotnet add package Keycloak.AuthServices.Authorization dotnet add package Keycloak.AuthServices.Sdk for the separate resource server pattern, also add: dotnet add package Keycloak.AuthServices.Authorization.Uma ``` -------------------------------- ### AuthGettingStarted Program.cs Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/examples/auth-getting-started.md This is the main program file for the AuthGettingStarted sample. It sets up the Keycloak authorization services and demonstrates basic usage. ```csharp using Keycloak.AuthServices.Sdk.Services; using Keycloak.AuthServices.Sdk.Services.Models; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; var builder = Host.CreateDefaultBuilder(args) .ConfigureLogging(logging => { logging.AddConsole(); }) .ConfigureServices((hostContext, services) => { services.AddKeycloakAuthorization( "https://localhost:8443/auth/", "myrealm", "myclientid", "clientsecret" ); services.AddHostedService(); }); await builder.Build().RunAsync(); public class AuthExampleService : IHostedService { private readonly ILogger _logger; private readonly IKeycloakAuthorizationService _keycloakAuthorizationService; public AuthExampleService( ILogger logger, IKeycloakAuthorizationService keycloakAuthorizationService) { _logger = logger; _keycloakAuthorizationService = keycloakAuthorizationService; } public async Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation("Starting AuthExampleService..."); var resource = new Resource("my-resource", "my-resource-type"); var permission = new Permission("my-permission", "my-permission-type"); var request = new AuthorizationRequest(resource, permission); var response = await _keycloakAuthorizationService.GetPermissionsAsync(request, cancellationToken); if (response.IsError) { _logger.LogError("Error getting permissions: {Error}", response.Error); } else { _logger.LogInformation("Permissions granted: {Granted}", response.Granted); } } public Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation("Stopping AuthExampleService..."); return Task.CompletedTask; } } ``` -------------------------------- ### Testing Endpoints with curl Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/samples/ClientSecretJwt/README.md Example cURL commands to test the application's protected endpoints after the sample has been started. ```bash # Or with curl: curl http://localhost:5099/realm curl http://localhost:5099/users ``` -------------------------------- ### Add Keycloak Admin HTTP Client Package Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/admin-rest-api/admin-api-kiota.md Installs the necessary NuGet package for the Keycloak Admin API client generated by Kiota. ```bash dotnet add package Keycloak.AuthServices.Sdk.Kiota ``` -------------------------------- ### Console App Setup with Keycloak Admin Client (Hand-Written SDK) Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/admin-sdk.md Demonstrates setting up the Keycloak Admin Client in a console application using dependency injection with custom options. ```csharp var services = new ServiceCollection(); var keycloakOptions = new KeycloakAdminClientOptions { AuthServerUrl = "http://localhost:8080/", Realm = "master", Resource = "admin-api", }; services.AddKeycloakAdminHttpClient(keycloakOptions); var sp = services.BuildServiceProvider(); var client = sp.GetRequiredService(); var realm = await client.GetRealmAsync("Test"); ``` -------------------------------- ### Get Realm using IKeycloakRealmClient (Hand-Written SDK) Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/admin-sdk.md Example of retrieving a specific Keycloak realm's configuration using the IKeycloakRealmClient interface. ```csharp app.MapGet("/realm", async (IKeycloakRealmClient client) => await client.GetRealmAsync("my-realm")); ``` -------------------------------- ### Keycloak Docker Installation Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-administration/SKILL.md Run Keycloak in development mode using Docker. This command starts a Keycloak instance with default admin credentials and exposes the management port. ```bash docker run -d \ --name keycloak \ -p 8080:8080 \ -e KEYCLOAK_ADMIN=admin \ -e KEYCLOAK_ADMIN_PASSWORD=admin \ quay.io/keycloak/keycloak:latest \ start-dev ``` -------------------------------- ### Get Keycloak Options Before DI Build Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/troubleshooting.md Access Keycloak configuration options directly from the IConfiguration object before the dependency injection container is built. This is useful for early configuration setup. ```csharp using Keycloak.AuthServices.Common; var options = configuration.GetKeycloakOptions()!; ``` -------------------------------- ### Create Aspire Starter Solution with Keycloak Import Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/devex.md Generates a full .NET Aspire solution including AppHost and API projects, with an option to enable Keycloak realm import. ```bash dotnet new keycloak-aspire-starter -o MyAspireSolution --EnableKeycloakImport ``` -------------------------------- ### Make Authenticated API Request with Curl Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/getting-started.md This example demonstrates how to make a GET request to a local API endpoint using curl, including the Authorization header with a Bearer token. It shows the request and a successful HTTP 200 OK response. ```bash curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" http://localhost:5228/ # * Trying 127.0.0.1:5228... # * Connected to localhost (127.0.0.1) port 5228 (#0) # > GET / HTTP/1.1 # > Host: localhost:5228 # > User-Agent: curl/8.1.2 # > Accept: */* # > Authorization: Bearer YOUR_ACCESS_TOKEN # > # < HTTP/1.1 200 OK # < Content-Type: text/plain; charset=utf-8 # < Date: Thu, 25 Apr 2024 15:13:36 GMT # < Server: Kestrel # < Transfer-Encoding: chunked # < # Hello World!* Connection #0 to host localhost left intact ``` -------------------------------- ### Build the .NET Solution Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/CLAUDE.md Builds the entire solution with a warning level of 0 and displays only errors. ```bash # Build the solution dotnet build -p:WarningLevel=0 /clp:ErrorsOnly ``` -------------------------------- ### Workspace API Controller Example Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/authorization/protected-resource-builder-mvc.md Example of an MVC controller demonstrating how to apply the ProtectedResourceAttribute to secure API endpoints. ```csharp using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Keycloak.AuthServices.Authorization.Core.Attributes; namespace TestWebApiWithControllers.Controllers { [ApiController] [Route("api/[controller]")] [Authorize] public class WorkspacesController : ControllerBase { [HttpGet] [ProtectedResource("workspaces", "read")] public IEnumerable Get() => new string[] { "value1", "value2" }; [HttpPost] [ProtectedResource("workspaces", "write")] public void Post([FromBody] string value) { } [HttpPut("{id}")] [ProtectedResource("workspaces", "write")] public void Put(int id, [FromBody] string value) { } [HttpDelete("{id}")] [ProtectedResource("workspaces", "delete")] public void Delete(int id) { } ``` -------------------------------- ### Run Keycloak Aspire Starter Project Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/devex/templates.md Builds and runs the Aspire application host for the Keycloak Aspire starter project. ```bash ❯ dotnet run --project $dev/KeycloakAspireStarter/AppHost/ # Building... # info: Aspire.Hosting.DistributedApplication[0] # Aspire version: 8.0.1+a6e341ebbf956bbcec0dda304109815fcbae70c9 # info: Aspire.Hosting.DistributedApplication[0] # Distributed application starting. # info: Aspire.Hosting.DistributedApplication[0] # Application host directory is: $dev\KeycloakAspireStarter\AppHost ``` -------------------------------- ### Create New Web Project Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/getting-started.md Use the dotnet CLI to create a new empty web project. This is the initial step for building your secured API. ```bash dotnet new web -n GettingStarted ``` -------------------------------- ### JWT Token Example Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/samples/AuthorizationAndCleanArchitecture/README.md An example of a JSON Web Token (JWT) payload issued by Keycloak, illustrating realm access, resource access, and other claims. ```json { "exp": 1642433984, "iat": 1642430384, "auth_time": 1642428609, "jti": "b89e599b-8c69-4707-b95d-af40b475de9c", "iss": "http://localhost:8088/auth/realms/authz", "aud": [ "workspace-authz", "account" ], "sub": "eefae679-99a3-44d1-b746-67e357dca78a", "typ": "Bearer", "azp": "frontend", "session_state": "167dcc27-30d0-43d5-a80e-b291d4ffa824", "acr": "0", "realm_access": { "roles": [ "SuperManager", "offline_access", "uma_authorization" ] }, "resource_access": { "workspace-authz": { "roles": [ "Manager" ] }, "account": { "roles": [ "manage-account", "manage-account-links", "view-profile" ] } }, "scope": "openid email profile", "email_verified": false, "preferred_username": "test" } ``` -------------------------------- ### Setup Keycloak Authorization Services Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/authorization/organizations.md Registers Keycloak authentication and authorization services in the .NET service collection. This setup is required before using authorization features. ```csharp var builder = WebApplication.CreateBuilder(args); builder.Services.AddKeycloakWebApiAuthentication(builder.Configuration); builder.Services.AddKeycloakAuthorization(); var app = builder.Build(); app.UseAuthentication(); app.UseAuthorization(); ``` -------------------------------- ### Generate Aspire Starter Project (Dry Run) Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/src/Keycloak.AuthServices.Templates/README.md Generates a new Keycloak Aspire Starter project in the specified directory without actually creating files. This command shows which files would be created. ```bash ❯ dotnet new keycloak-aspire-starter -o $dev/KeycloakAspireStarter --EnableKeycloakImport --dry-run File actions would have been taken: # Create: $dev\KeycloakAspireStarer\.gitignore # Create: $dev\KeycloakAspireStarer\Api\Api.csproj # Create: $dev\KeycloakAspireStarer\Api\Extensions.OpenApi.cs # Create: $dev\KeycloakAspireStarer\Api\Program.cs # Create: $dev\KeycloakAspireStarer\Api\Properties\launchSettings.json # Create: $dev\KeycloakAspireStarer\Api\appsettings.Development.json # Create: $dev\KeycloakAspireStarer\Api\appsettings.json # Create: $dev\KeycloakAspireStarer\AppHost\AppHost.csproj # Create: $dev\KeycloakAspireStarer\AppHost\KeycloakConfiguration\Test-realm.json # Create: $dev\KeycloakAspireStarer\AppHost\KeycloakConfiguration\Test-users-0.json # Create: $dev\KeycloakAspireStarer\AppHost\Program.cs # Create: $dev\KeycloakAspireStarer\AppHost\Properties\launchSettings.json # Create: $dev\KeycloakAspireStarer\AppHost\appsettings.Development.json # Create: $dev\KeycloakAspireStarer\AppHost\appsettings.json # Create: $dev\KeycloakAspireStarer\KeycloakAspireStarter.sln # Create: $dev\KeycloakAspireStarer\Directory.Build.props # Create: $dev\KeycloakAspireStarer\Directory.Packages.props # Create: $dev\KeycloakAspireStarer\README.md # Create: $dev\KeycloakAspireStarer\ServiceDefaults\Extensions.cs # Create: $dev\KeycloakAspireStarer\ServiceDefaults\ServiceDefaults.csproj # Create: $dev\KeycloakAspireStarer\global.json ``` -------------------------------- ### Custom Parameter Resolver Example Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/resource-protection.md An example of a custom IParameterResolver that retrieves a tenant ID from a configuration service. This can be used to dynamically resolve parameters in resource protection rules. ```csharp public class ServiceResolver : IParameterResolver { public string? Resolve(string parameter, HttpContext httpContext, IServiceProvider serviceProvider) { var tenantConfig = serviceProvider.GetService(); return tenantConfig?.TenantId; } } ``` -------------------------------- ### Program.cs Configuration for Authorization Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/examples/auth-clean-arch.md Sets up the .NET application, including Keycloak authorization services and dependency injection. This is the entry point for the application's configuration. ```csharp using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Identity.Web; using System.Security.Claims; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // Add Keycloak Authentication builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd")); // Add Keycloak Authorization builder.Services.AddAuthorization(options => { // Example: Require a specific scope for all endpoints options.FallbackPolicy = options.DefaultPolicy; // Example: Require a specific role for an endpoint options.AddPolicy("AdminPolicy", policy => policy.RequireClaim(ClaimTypes.Role, "admin")); }); // Add custom authorization handler (optional) builder.Services.AddSingleton(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run(); // Custom authorization handler to check for specific scopes public partial class Program { } public class HasScopeHandler : AuthorizationHandler { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasScopeRequirement requirement) { // If the user has the required scope, then the requirement is met if (context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer)) { context.Succeed(requirement); } return Task.CompletedTask; } } public class HasScopeRequirement : IAuthorizationRequirement { public string Issuer { get; } public HasScopeRequirement(string issuer) { Issuer = issuer; } } ``` -------------------------------- ### Configure Keycloak Configuration Source from File Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/authentication.md Sets up the host to use a standalone 'keycloak.json' file for configuration instead of appsettings.json. This is useful for managing Keycloak specific settings separately. ```csharp var builder = WebApplication.CreateBuilder(args); builder.Host.ConfigureKeycloakConfigurationSource("keycloak.json"); builder.Services.AddKeycloakWebApiAuthentication(builder.Configuration); ``` -------------------------------- ### Scaffold Keycloak Aspire Starter Project Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/devex/aspire.md Scaffold a new .NET Aspire solution using the keycloak-aspire-starter template, with Keycloak integration pre-configured and import enabled. ```bash dotnet new keycloak-aspire-starter -o $dev/KeycloakAspireStarter --EnableKeycloakImport ``` -------------------------------- ### Self-Contained Pattern: Authentication and Authorization Setup Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/protection-api/uma.md Configure OIDC authentication for web applications and Keycloak authorization with named policies. This setup is for a single app acting as both OIDC client and resource server. ```csharp // OIDC authentication (cookie-based, for browser login) services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddKeycloakWebApp(configuration.GetSection("Keycloak"), configureOpenIdConnectOptions: options => { options.SaveTokens = true; options.MapInboundClaims = false; // keep "sub" claim name }); // Keycloak authorization with named policies services.AddAuthorization() .AddKeycloakAuthorization() .AddAuthorizationBuilder() .AddPolicy("UmaRead", policy => policy.RequireProtectedResource("shared-document", "read")) .AddPolicy("UmaWrite", policy => policy.RequireProtectedResource("shared-document", "write")); // Authorization server client (evaluates permissions against Keycloak) services.AddAuthorizationServer(options => { configuration.GetSection("Keycloak").BindKeycloakOptions(options); options.Resource = "uma-resource-server"; options.Credentials = new() { Secret = "uma-resource-server-secret" }; }) .AddStandardResilienceHandler(); // Protection API client (permission ticket management) services.AddKeycloakProtectionHttpClient(options => { configuration.GetSection("Keycloak").BindKeycloakOptions(options); options.Resource = "uma-resource-server"; options.Credentials = new() { Secret = "uma-resource-server-secret" }; }) .AddClientCredentialsTokenHandler(tokenClientName); ``` -------------------------------- ### Console App: Initialize and Use Keycloak Admin Client Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/admin-rest-api/admin-rest-api.md Example of setting up Keycloak Admin client services in a console application using dependency injection and making a call to retrieve a realm. Note: Authentication is required for actual API calls. ```csharp var services = new ServiceCollection(); var keycloakOptions = new KeycloakAdminClientOptions { AuthServerUrl = "http://localhost:8080/", Realm = "master", Resource = "admin-api", }; services.AddKeycloakAdminHttpClient(keycloakOptions); var sp = services.BuildServiceProvider(); var client = sp.GetRequiredService(); var realm = await client.GetRealmAsync("Test"); ``` -------------------------------- ### Generate Keycloak Aspire Starter Project Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/devex/templates.md Generates a new Keycloak Aspire starter project, enabling automatic Keycloak realm import with the `--EnableKeycloakImport` option. ```bash ❯ dotnet new keycloak-aspire-starter -o $dev/KeycloakAspireStarter --EnableKeycloakImport # The template "Keycloak Aspire Starter" was created successfully. ``` -------------------------------- ### Create Web API Project with Keycloak Auth Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/devex.md Scaffolds a new Web API project pre-configured with Keycloak authentication. ```bash dotnet new keycloak-webapi -o MyKeycloakApi ``` -------------------------------- ### Dry Run: Generate Keycloak Aspire Starter Project Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/devex/templates.md Verifies file actions for generating a Keycloak Aspire starter project with automatic realm import enabled, without creating files. ```bash ❯ dotnet new keycloak-aspire-starter -o $dev/KeycloakAspireStarter --EnableKeycloakImport --dry-run # File actions would have been taken: # Create: $dev\KeycloakAspireStarter\.gitignore # Create: $dev\KeycloakAspireStarter\Api\Api.csproj # Create: $dev\KeycloakAspireStarter\Api\Extensions.OpenApi.cs # Create: $dev\KeycloakAspireStarter\Api\Program.cs # Create: $dev\KeycloakAspireStarter\Api\Properties\launchSettings.json # Create: $dev\KeycloakAspireStarter\Api\appsettings.Development.json # Create: $dev\KeycloakAspireStarter\Api\appsettings.json # Create: $dev\KeycloakAspireStarter\AppHost\AppHost.csproj # Create: $dev\KeycloakAspireStarter\AppHost\KeycloakConfiguration\Test-realm.json # Create: $dev\KeycloakAspireStarter\AppHost\KeycloakConfiguration\Test-users-0.json # Create: $dev\KeycloakAspireStarter\AppHost\Program.cs # Create: $dev\KeycloakAspireStarter\AppHost\Properties\launchSettings.json # Create: $dev\KeycloakAspireStarter\AppHost\appsettings.Development.json # Create: $dev\KeycloakAspireStarter\AppHost\appsettings.json # Create: $dev\KeycloakAspireStarter\Directory.Build.props # Create: $dev\KeycloakAspireStarter\Directory.Packages.props # Create: $dev\KeycloakAspireStarter\KeycloakAspireStarter.sln # Create: $dev\KeycloakAspireStarter\README.md # Create: $dev\KeycloakAspireStarter\ServiceDefaults\Extensions.cs # Create: $dev\KeycloakAspireStarter\ServiceDefaults\ServiceDefaults.csproj # Create: $dev\KeycloakAspireStarter\global.json ``` -------------------------------- ### Example Metrics Output Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/opentelemetry.md Sample output from the .NET counters monitor showing current values for Keycloak.AuthServices.Authorization metrics, including requirement success and failure counts. ```text Press p to pause, r to resume, q to quit. Status: Running Name Current Value [Keycloak.AuthServices.Authorization] keycloak.authservices.requirements.fail (Count) requirement=ParameterizedProtectedResourceRequirement 3 keycloak.authservices.requirements.succeed (Count) requirement=ParameterizedProtectedResourceRequirement 5 requirement=RealmAccessRequirement 16 ``` -------------------------------- ### AppHost Program Configuration Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/examples/aspire-web-api.md This C# code configures the AppHost for the Aspire Web API sample. It sets up the Keycloak instance and integrates it with the application. ```csharp using Aspire.Hosting; using Aspire.Hosting.Keycloak; var builder = DistributedApplication.CreateBuilder(args); var keycloak = builder.AddKeycloak("keycloak") .WithAdminPassword("admin") .WithRealmFile("keycloak.json"); var api = builder.AddProject() .WithReference(keycloak); builder.Build().Run(); ``` -------------------------------- ### Get Bearer Token Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/samples/OAuthServerMetadata/README.md Obtains a bearer token from Keycloak and saves it to a .env file. ```bash # 3. Get a bearer token and save to .env bash ./assets/get-token.sh > .env ``` -------------------------------- ### KeycloakAuthorizationOptions Configuration Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/configuration.md Example JSON configuration for Keycloak authorization options. This is used by the Keycloak.AuthServices.Authorization package. ```json { "Keycloak": { "resource": "test-client", "EnableRolesMapping": "None", "RolesResource": "test-client", "RoleClaimType": "role" } } ``` -------------------------------- ### KeycloakAuthenticationOptions Configuration Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/configuration.md Example JSON configuration for Keycloak authentication options. This is used by the Keycloak.AuthServices.Authentication package. ```json { "Keycloak": { "realm": "Test", "auth-server-url": "http://localhost:8080/", "ssl-required": "none", "resource": "test-client", "verify-token-audience": true, "confidential-port": 0, "credentials": { "secret": "your-secret" } } } ``` -------------------------------- ### KeycloakProtectionClientOptions Configuration Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/configuration.md Example JSON configuration for Keycloak Protection API client options. Used by the Keycloak.AuthServices.Sdk package. ```json { "Keycloak": { "realm": "my-realm", "auth-server-url": "http://localhost:8080/", "resource": "my-client", "credentials": { "secret": "your-secret" } } } ``` -------------------------------- ### KeycloakAdminClientOptions Configuration Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/skills/keycloak-auth-services/references/configuration.md Example JSON configuration for Keycloak Admin API client options. Used by the Keycloak.AuthServices.Sdk package. ```json { "Keycloak": { "realm": "master", "auth-server-url": "http://localhost:8080/", "resource": "admin-api", "credentials": { "secret": "your-secret" } } } ``` -------------------------------- ### Configure HttpClient with Resilience and Handlers Source: https://github.com/nikiforovall/keycloak-authorization-services-dotnet/blob/main/docs/admin-rest-api/admin-rest-api.md Configure the underlying HttpClient with Polly resilience policies and custom delegating handlers. This example shows how to add standard resilience, a timing handler, and a validation handler. ```csharp services .AddKeycloakAdminHttpClient(configuration) .AddStandardResilienceHandler() .AddHttpMessageHandler() .AddHttpMessageHandler(); ```