This tutorial provides a step-by-step guide to integrating Keycloak authorization with an ASP.NET Core application this README is derived from here
- .NET 6.0 or later
- ASP.NET Core 8.0 setup
- Keycloak 25.0.2
Follow the official ASP.NET Core tutorial to set up your first Web API using ASP.NET Core 8.0.
- Download and Install Keycloak:
- Download
keycloak-25.0.2.zipfrom here. - Extract the ZIP file.
- Run Keycloak in development mode:
bin\kc.bat start-dev
- Download
- Configure Keycloak:
- Open a browser and go to
http://localhost:8080/. - Complete the admin setup.
- Create a new realm.
- Create a client with:
- Client authentication enabled.
- A redirect URI to allow your API to receive authentication responses from Keycloak.
- Retrieve the client secret from the ‘Credentials’ tab.
- Create a user and set a password.
- Return to the newly created client, create a role, and assign the user to the role.
- Open a browser and go to
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Microsoft.IdentityModel.Protocols.OpenIdConnectAdd the following configuration:
{
"Authentication": {
"Keycloak": {
"Authority": "http://localhost:8080/realms/todorealm",
"Audience": "account",
"RequireHttpsMetadata": false
}
}
}Modify Program.cs to configure authentication and authorization:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
var builder = WebApplication.CreateBuilder(args);
ConfigureServices(builder.Services, builder.Configuration);
var app = builder.Build();
ConfigureMiddleware(app);
app.Run();
void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddControllers();
services.AddDbContext<TodoContext>(opt => opt.UseInMemoryDatabase("TodoList"));
services.AddEndpointsApiExplorer();
services.AddSwaggerGen();
ConfigureAuthentication(services, configuration); // <-- MODIFICATION
services.AddAuthorization();
}
//MODIFICATION
void ConfigureAuthentication(IServiceCollection services, IConfiguration configuration)
{
var keycloakSettings = configuration.GetSection("Authentication:Keycloak");
var authority = keycloakSettings["Authority"];
var audience = keycloakSettings["Audience"];
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Authority = authority;
options.Audience = audience;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = authority,
ValidateAudience = true,
ValidAudience = audience,
ValidateLifetime = true
};
});
}
void ConfigureMiddleware(WebApplication app)
{
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();// <-- MODIFICATION
app.UseAuthorization();
app.MapControllers();
}Apply the [Authorize] attribute to relevant controllers.
-
Configure Authorization Policies: Add the following method to
Program.cs:void ConfigureAuthorization(IServiceCollection services, IConfiguration configuration) { services.AddAuthorization(opt => { opt.AddPolicy("Policy1", policy => { policy.RequireAuthenticatedUser(); policy.RequireAssertion(context => { // Policy Conditions }); }); opt.AddPolicy("Policy2", policy => { policy.RequireRole("role_1"); }); }); }
-
Update
ConfigureServices: Replaceservices.AddAuthorization();withConfigureAuthorization(services, configuration);. -
Apply Policies to Controllers: Replace
[Authorize]with[Authorize(Policy = "PolicyX")]in your controllers.
curl -X POST "http://localhost:8080/realms/<your-realm>/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=<your-client-id>" \
-d "client_secret=<your-client-secret>" \
-d "grant_type=password" \
-d "username=<username>" \
-d "password=<user-password>"curl -X POST 'http://localhost:5272/api/TodoItems' \
-H 'accept: text/plain' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-token>' \
-d '{"id":0,"name":"string","isComplete":true}'curl -X GET 'http://localhost:5272/api/TodoItems' \
-H 'accept: text/plain' \
-H 'Authorization: Bearer <access-token>'I have provide a python script RequestScript.py that sends 10 POST and 1 GET requests, depending on your policies, users may receive various responses.