I played a little with this today. The easiest way is to use the 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 the 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 configured as follows:
If I want to authorize a user by role, I do something like this:
Add authorization for claims in the ConfigureServices method:
public void ConfigureServices(IServiceCollection services) { (...) services.AddAuthorization(options => { options.AddPolicy("Accounting", policy => policy.RequireClaim("member_of", "[accounting]"));
I edited the get method in ValuesController (default web API template):
[Authorize(Policy = "Accounting")] [Route("api/[controller]")] public class ValuesController : Controller {
If I log in with a user who has an account role or is a member of a group that performs an account role, he should display my user statements at localhost: 57630 / api / values.
I hope this works for you.
Edit: .NET Core 2 Hello everyone! The way my application works has changed a bit, and I have not yet fully tested .NET Core 2, but you can still try connecting to Keycloak as follows 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;
And in Configure:
app.UseAuthentication();
You can access your token later using 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.