Keycloak client for ASP.NET Core

早过忘川 提交于 2019-12-04 13:30:00

问题


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)?


回答1:


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.




回答2:


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")]



回答3:


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;
}


来源:https://stackoverflow.com/questions/41721032/keycloak-client-for-asp-net-core

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!