Token Introspection
cs
using System.Security.Claims;
using Keycloak.AuthServices.Authorization;
using Microsoft.AspNetCore.Authentication;
var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;
var services = builder.Services;
var useCustomTransform = configuration.GetValue<bool>("CustomTransform");
services.AddKeycloakWebApiAuthentication(configuration);
if (useCustomTransform)
{
services.AddTransient<IClaimsTransformation, CustomClaimsTransformation>();
}
services
.AddKeycloakAuthorization(options =>
{
configuration.GetSection("Keycloak").Bind(options);
options.EnableRolesMapping = RolesClaimTransformationSource.All;
})
.AddAuthorizationBuilder()
.AddPolicy("AdminOnly", policy => policy.RequireRealmRoles("Admin"));
services.AddKeycloakTokenIntrospection(configuration);
var app = builder.Build();
app.UseAuthentication().UseAuthorization();
app.MapGet(
"/me",
(ClaimsPrincipal user) =>
Results.Ok(
new
{
user.Identity?.Name,
Claims = user.Claims.Select(c => new { c.Type, c.Value }),
}
)
)
.RequireAuthorization();
app.MapGet(
"/roles",
(ClaimsPrincipal user) =>
{
var roles = user.Claims.Where(c => c.Type == "role").Select(c => c.Value).ToList();
return Results.Ok(new { Roles = roles });
}
)
.RequireAuthorization();
app.MapGet("/admin", () => Results.Ok(new { Message = "Admin area" }))
.RequireAuthorization("AdminOnly");
await app.RunAsync();
internal sealed class CustomClaimsTransformation : IClaimsTransformation
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
var identity = principal.Identity as ClaimsIdentity;
if (identity is not null && !identity.HasClaim("custom_marker", "true"))
{
identity.AddClaim(new Claim("custom_marker", "true"));
}
return Task.FromResult(principal);
}
}See sample source code: keycloak-authorization-services-dotnet/tree/main/samples/TokenIntrospection