I have a keycloak server deployed to production and I am trying to get roles to work properly within my .net core mvc app. The token from keycloak is returning the roles. I am able to be redirected and authenticated from keycloak perfectly fine. I just can’t seem to get any roles to work.
Startup.cs:
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "/Account/Login";
})
.AddOpenIdConnect(options =>
{
options.Authority = "https://MyServer/auth/realms/ATG";
options.MetadataAddress = "https://MyServer/realms/ATG/.well-known/openid-configuration";
options.ClientId = "ATG.ad.yaskawa.com";
options.ClientSecret = "tpdyzbDOADYdsCUaoFz9bTJNqRsOsrcQ";
options.ResponseType = "code";
options.SaveTokens = true;
options.Scope.Add("openid");
options.CallbackPath = "/signin-oidc"; // Update callback path
options.SignedOutCallbackPath = "/signout-callback-oidc"; // Update signout callback path
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "preferred_username",
RoleClaimType = "roles"
};
});
builder.Services.AddTransient<IClaimsTransformation, CustomRoleClaimsTransformation>();
//Fix Telerik camelCase to PascalCase
builder.Services.AddControllersWithViews().AddJsonOptions(options =>
options.JsonSerializerOptions.PropertyNamingPolicy = null); ;
ConfigurationManager configuration = builder.Configuration;
IdentityModelEventSource.ShowPII = true;
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
Token:
{
“exp”: 1720548651,
“iat”: 1720548351,
“auth_time”: 1720548351,
“jti”: “b9aca179-91c9-4528-834e-29f5d33e0308”,
“iss”: “https://MyServer/realms/ATG”,
“aud”: “account”,
“sub”: “1ab9a926-d2a9-4941-9a01-ffe07d500abd”,
“typ”: “Bearer”,
“azp”: “ATG.ad.yaskawa.com”,
“sid”: “fd0c995d-3ec7-4bec-8a0c-18449b393ee8”,
“acr”: “1”,
“scope”: “email profile”,
“email_verified”: true,
“roles”: [
“Admin”,
“view-profile”
],
“name”: “Eric Obermuller”,
“preferred_username”: “[email protected]”,
“given_name”: “Eric”,
“family_name”: “O”,
“email”: “[email protected]”
}
So from here I am really not surewhat to do. I tried using a custom role transformation but nothing about the “roles” property is coming into principal.identity
public class CustomRoleClaimsTransformation : IClaimsTransformation
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
var identity = (ClaimsIdentity)principal.Identity;
// Ensure roles are being extracted and mapped correctly
var roles = identity.FindAll("roles").Select(c => c.Value).ToList();
foreach (var role in roles)
{
identity.AddClaim(new Claim(ClaimTypes.Role, role));
}
return Task.FromResult(principal);
}
}