Is there any existing Keycloak client for Asp.net Core? I have found a NuGet package for .net but it doesn't work with Core. Do you have any ideas how to easily integrate with this security server (or maybe using any other alternatives)?
-
Have you found any resources for this? – devqon Apr 26 '17 at 11:51
-
Try using UseOpenIdConnectAuthentication from Microsoft.AspNetCore.Authentication.OpenIdConnect with OpenIdConnectOptions filled for Keycloak (Authority: server+"auth/realms/"+realm, ClientId, ClientSecret). – Michał J. Gąsior Apr 27 '17 at 12:21
-
@mikes do you know of an online sample of this configuration you are suggesting with AspNetCore and keycloak? Just out of curiosity, why don't you provide your answer below in the answer as opposed to a comment? Wondering of the difference in SO... – Talisker May 03 '17 at 02:40
-
@Talisker just didn't think about it. ;) The answer is available right now. – Michał J. Gąsior May 05 '17 at 08:20
-
1Won't this library help here - https://github.com/lvermeulen/Keycloak.Net – Anshuman Chatterjee Jun 11 '21 at 03:53
-
It might, but I'm kind of off this problem for a few years already. Thanks for the bump tho! :) – Michał J. Gąsior Jun 22 '21 at 14:53
-
Is Keycloak.net still supported? The docs are no longer available. – Connie DeCinko Aug 18 '22 at 17:40
-
I have no idea. I don't work with .net any more. – Michał J. Gąsior Aug 23 '22 at 07:45
5 Answers
I've played a bit with this today. The most straightforward way is too use OpenId standard.
In Startup.cs I used OpenIdConnect Authentication:
public void Configure(...)
{ (...)
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme,
AutomaticAuthenticate = true,
CookieHttpOnly = true,
CookieSecure = CookieSecurePolicy.SameAsRequest
});
app.UseOpenIdConnectAuthentication(CreateKeycloakOpenIdConnectOptions());`(...)
}`
OpenIdConnectOptions method:
private OpenIdConnectOptions CreateKeycloakOpenIdConnectOptions()
{
var options = new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme,
Authority = Configuration["Authentication:KeycloakAuthentication:ServerAddress"]+"/auth/realms/"+ Configuration["Authentication:KeycloakAuthentication:Realm"],
RequireHttpsMetadata = false, //only in development
PostLogoutRedirectUri = Configuration["Authentication:KeycloakAuthentication:PostLogoutRedirectUri"],
ClientId = Configuration["Authentication:KeycloakAuthentication:ClientId"],
ClientSecret = Configuration["Authentication:KeycloakAuthentication:ClientSecret"],
ResponseType = OpenIdConnectResponseType.Code,
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true
};
options.Scope.Add("openid");
return options;
}
In appsettings.json add configuration for Keycloak:
{
(...),
"Authentication": {
"KeycloakAuthentication": {
"ServerAddress": "http://localhost:8180",
"Realm": "demo",
"PostLogoutRedirectUri": "http://localhost:57630/",
"ClientId": "KeycloakASPNETCore",
"ClientSecret": "secret-get-it-in-keycloakConsole-client-credentials"
}
}
}
Keycloak client is configuerd as followed:
- Client settings,
- I've added 'accounting' role for test,
- I added mapper 'member_of' of type 'User Client Role' for roles so that roles are added in the claims
If I want to Authorize user by role I do something like this:
Add authorization by claims in ConfigureServices method:
public void ConfigureServices(IServiceCollection services)
{
(...)
services.AddAuthorization(options =>
{
options.AddPolicy("Accounting", policy =>
policy.RequireClaim("member_of", "[accounting]")); //this claim value is an array. Any suggestions how to extract just single role? This still works.
});
}
I've edited get method in ValuesController (Default Web API template):
[Authorize(Policy = "Accounting")]
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
public Dictionary<string,string> Get()
{
var userPrinciple = User as ClaimsPrincipal;
var claims = new Dictionary<string, string>();
foreach (var claim in userPrinciple.Claims)
{
var key = claim.Type;
var value = claim.Value;
claims.Add(key, value);
}
return claims;
}
If I login with user that has accounting role or is in group that has accounting role, it should display my user claims on address localhost:57630/api/values.
I hope this works for you.
Edit: .NET Core 2 Hi everyone! The way my app works changed quite a bit and I have not fully tested .NET Core 2 yet, but you can still try connecting to Keycloak like this in ConfigureServices:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = Configuration["Authentication:KeycloakAuthentication:ServerAddress"] + "/auth/realms/" + Configuration["Authentication:KeycloakAuthentication:Realm"];
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidAudiences = new string[] { "curl", "financeApplication", "accountingApplication", "swagger"}
};
options.RequireHttpsMetadata = false; //for test only!
options.SaveToken = true;
options.Validate();
});
And in Configure:
app.UseAuthentication();
You can access your token later with IHttpContextAccessor httpContextAccessor, for example:
public KeycloakAuthorizationRequirementHandler(IConfiguration config,
IHttpContextAccessor httpContextAccessor,
IMemoryCache memoryCache)
{
_config = config;
_httpContextAccessor = httpContextAccessor;
_memoryCache = memoryCache;
}
//get accessToken
var accessToken = _httpContextAccessor.HttpContext.GetTokenAsync("access_token");
_httpContextAccessor.HttpContext.Items["username"] = username;
Tell me how it goes.

- 486
- 5
- 6
-
Very useful and complete answer! The only thing I can't get to work is the mapper `member_of`, it's not present in the list of user claims. Would you mind sharing the settings you used to create it? Thanks. – Gimly Jul 19 '17 at 14:13
-
1You can create 'member_of' by clicking 'Create' in the 'Mappers' tab of your client. 'Mapper Type' should be set to 'User Client Role' and 'Add to ID token' - on. After you logout your user, changes should be visible in user claims. – frogec Jul 23 '17 at 07:02
-
1@gimly If user has more than 1 role, you can authorize by using Custom Policy-Based Authorization where you check each of your users roles. – frogec Jul 23 '17 at 07:16
-
Thanks for your help, the reason why I couldn't see it on the claims was that I hadn't given a claim name. Now it's working correctly. – Gimly Jul 24 '17 at 08:36
-
@frogec could you give an example of authorizing a user who has more than one role in keycloak? I am normally in the javaworld nowadays but now I have to create a PoC for .net core and don't get it to work with more than one role :/ – Dominik Feb 19 '19 at 08:54
-
1okay, actually this seems to be outdated as of .net core 2. Would be great to get an update! :) – Dominik Feb 19 '19 at 09:33
If you want to use standard .Net Role mappings with Keycloak Client Roles, setup like so:
Startup.cs:
services.AddAuthorization(options =>
{
options.AddPolicy("Users", policy =>
policy.RequireRole("Users"));
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.Authority = Configuration["Authentication:oidc:Authority"]
options.ClientId = Configuration["Authentication:oidc:ClientId"];
options.ClientSecret = Configuration["Authentication:oidc:ClientSecret"];
options.RequireHttpsMetadata = false;
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.RemoteSignOutPath = "/SignOut";
options.SignedOutRedirectUri = "Redirect-here";
options.ResponseType = "code";
});
appsettings.json:
"Authentication": {
"oidc": {
"Authority":"http://your-keycloak-server/auth/realms/your-realm",
"ClientId":"Your-Client-Name",
"ClientSecret":"Your-client-secret"
}
}
Keycloak Client Settings:
- Create new Token Mapper
- Mapper-Values (enter your own client name)
Now you can use standard authorize role statements to apply your Keycloak Client Roles to your ASP.NET project:
[Authorize(Roles = "Users")]

- 111
- 1
- 3
-
1just to be clear: for /Signout I should use the logout-endpoint of my keycloak-realm, shouldn't I? Or did you create a ressource under /signout which calls that internally and creates a logoutpage or something? – Dominik Feb 19 '19 at 09:43
-
1Either will work, just depends on what you're requirements are. If you need to intercept any portion of the logout process, say to keep the user on your UI instead of redirecting to keycloak, then you would create your own signout and implement the keycloak API to logout. Otherwise, the keycloak logout endpoint will suffice. – Imagin8 May 04 '19 at 17:07
-
1Also to be clear, the above configuration will check keycloak, automatically get the signout path, and assign it to "/SignOut" in your application. This is the options.RemoteSignOutPath configuration setting. – Imagin8 May 04 '19 at 17:11
-
Hey, I am having trouble logging out. The app re-authenticates the user automatically. I am calling: `do! ctx.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme)` and `do! ctx.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme)` (I used F# with Saturn). Any idea what's wrong? Is there anything special that has to be done upon logging out? – boggy Jun 15 '20 at 07:25
For those who building KeyCloak-based authentication for .Net 6 backend and looking for JWT-token based solution here is a code to add in ConfigureServices of your app with Delobytes.AspNetCore.Infrastructure client:
services.AddKeyCloakAuthentication("SchemeName", true, options =>
{
options.Authority = "https://mykeycloakinstallation.com/auth/realms/myrealm"; //"issuer" endpoint
options.Audience = "account";
options.OpenIdConfigurationEndpoint = "https://mykeycloakinstallation.com/auth/realms/myrealm/.well-known/openid-configuration";
options.TokenValidationParameters = new TokenValidationOptions
{
RequireExpirationTime = true,
RequireSignedTokens = true,
ValidateIssuer = true,
ValidIssuer = "https://mykeycloakinstallation.com/auth/realms/myrealm",
ValidateAudience = true,
ValidAudience = "account",
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(2),
};
});

- 173
- 1
- 1
- 8
The thing that worked for us was setting these things in Startup.cs (it's cookie based authentication):
public void Configure(...)
{
(...)
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme,
AutomaticAuthenticate = true,
CookieHttpOnly = true,
CookieSecure = CookieSecurePolicy.SameAsRequest
});
app.UseOpenIdConnectAuthentication(CreateOpenIdConnectOptions(_customConfig));
(...)
}
And setting up the options:
private OpenIdConnectOptions CreateOpenIdConnectOptions(CustomConfigurationFile configuration)
{
var options = new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme,
Authority = configuration.ServerAddress + "/auth/realms/" + configuration.Realm,
RequireHttpsMetadata = true,
PostLogoutRedirectUri = configuration.SystemAddress,
ClientId = configuration.ClientId,
ClientSecret = configuration.ClientSecret,
ResponseType = OpenIdConnectResponseType.Code,
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true
};
options.Scope.Clear();
options.Scope.Add("openid");
return options;
}

- 1,457
- 3
- 21
- 39
-
3Does this solution allow you to use standard authorization attributes such as [Autorize(Roles="MyKeycloakRole")] ? In other terms, are KeyCloak-defined roles extracted automatically through OpenIdConnectAuthentication? cheers – Talisker May 05 '17 at 20:10
-
@Talisker did you find a solution / answer to this? Otherwise keycloak and your service is strongly coupled. – Lukas Hieronimus Adler May 12 '20 at 07:19
Could we get an up-to-date answer on this question with .net core 5+? I've recently installed keycloak version 13.0.0 & its working allowing me to use single sign on with a couple apps. Now for the real reason I installed keycloak, for webapi authentication. Based on the answers above I've installed Microsoft.AspNetCore.Authentication.OpenIdConnect & have been working to get this to work on both the webapi side and on the client side.

- 586
- 5
- 13
-
You can try to use this library https://github.com/lvermeulen/Keycloak.Net – Michał J. Gąsior Jul 06 '21 at 11:47