【问题标题】:Keycloak client for ASP.NET CoreASP.NET Core 的 Keycloak 客户端
【发布时间】:2017-06-02 22:14:31
【问题描述】:

是否有任何现有的用于 Asp.net Core 的 Keycloak 客户端? I have found a NuGet package for .net 但它不适用于 Core。您对如何轻松与此安全服务器集成(或使用任何其他替代方案)有任何想法吗?

【问题讨论】:

  • 你有没有找到这方面的资源?
  • 尝试使用 Microsoft.AspNetCore.Authentication.OpenIdConnect 中的 UseOpenIdConnectAuthentication 并为 Keycloak 填充 OpenIdConnectOptions(权限:server+"auth/realms/"+realm, ClientId, ClientSecret)。
  • @mikes 您知道您建议使用 AspNetCore 和 keycloak 的此配置的在线示例吗?只是出于好奇,您为什么不在下面的答案中提供答案而不是评论?想知道 SO...的区别...
  • @Talisker 只是没想到。 ;) 答案现在可用。
  • 这个库对这里有帮助吗 - github.com/lvermeulen/Keycloak.Net

标签: asp.net .net asp.net-core .net-core keycloak


【解决方案1】:

对我们有用的是在 Startup.cs 中设置这些东西(它是基于 cookie 的身份验证):

public void Configure(...)
{
    (...)
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme,
        AutomaticAuthenticate = true,
        CookieHttpOnly = true,
        CookieSecure = CookieSecurePolicy.SameAsRequest
    });

    app.UseOpenIdConnectAuthentication(CreateOpenIdConnectOptions(_customConfig));
    (...)
}

并设置选项:

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

【讨论】:

  • 此解决方案是否允许您使用标准授权属性,例如 [Autorize(Roles="MyKeycloakRole")] ?换句话说,KeyCloak 定义的角色是通过 OpenIdConnectAuthentication 自动提取的吗?欢呼
  • @Talisker 您找到解决方案/答案了吗?否则 keycloak 和你的服务是强耦合的。
【解决方案2】:

我今天玩了一点。最直接的方式也是使用 OpenId 标准。

在 Startup.cs 中我使用了 OpenIdConnect 身份验证:

    public void Configure(...)
    { (...)
         app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme,
            AutomaticAuthenticate = true,
            CookieHttpOnly = true,
            CookieSecure = CookieSecurePolicy.SameAsRequest
        });
        app.UseOpenIdConnectAuthentication(CreateKeycloakOpenIdConnectOptions());`(...)
 }`

OpenIdConnectOptions 方法:

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

在 appsettings.json 中为 Keycloak 添加配置:

{
  (...),
  "Authentication": {
    "KeycloakAuthentication": {
      "ServerAddress": "http://localhost:8180",
      "Realm": "demo",
      "PostLogoutRedirectUri": "http://localhost:57630/",
      "ClientId": "KeycloakASPNETCore",
      "ClientSecret": "secret-get-it-in-keycloakConsole-client-credentials"
    }
  }
}

Keycloak 客户端配置如下:

如果我想按角色授权用户,我会这样做:

在 ConfigureServices 方法中添加authorization by claims

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

我在 ValuesController(默认 Web API 模板)中编辑了 get 方法:

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

如果我使用具有会计角色的用户或在具有会计角色的组中登录,它应该在地址 localhost:57630/api/values 上显示我的用户声明。

我希望这对你有用。

编辑:.NET Core 2 大家好!我的应用程序的工作方式发生了很大变化,我还没有完全测试 .NET Core 2,但您仍然可以尝试在 ConfigureServices 中像这样连接到 Keycloak:

        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();

            });

在配置中:

app.UseAuthentication();

您可以稍后使用 IHttpContextAccessor httpContextAccessor 访问您的令牌,例如:

public KeycloakAuthorizationRequirementHandler(IConfiguration config,
            IHttpContextAccessor httpContextAccessor,
            IMemoryCache memoryCache)
        {
            _config = config;
            _httpContextAccessor = httpContextAccessor;
            _memoryCache = memoryCache;
        }

//获取访问令牌

var accessToken = _httpContextAccessor.HttpContext.GetTokenAsync("access_token");

_httpContextAccessor.HttpContext.Items["username"] = username;

告诉我进展如何。

【讨论】:

  • 非常有用且完整的答案!我唯一无法工作的是映射器member_of,它不在用户声明列表中。你介意分享你用来创建它的设置吗?谢谢。
  • 您可以通过单击客户端“映射器”选项卡中的“创建”来创建“member_of”。 “映射器类型”应设置为“用户客户端角色”和“添加到 ID 令牌” - 开启。注销用户后,更改应在用户声明中可见。
  • @gimly 如果用户拥有多个角色,您可以使用基于策略的自定义授权进行授权,您可以在其中检查每个用户的角色。
  • 感谢您的帮助,我在索赔中看不到它的原因是我没有给出索赔名称。现在它可以正常工作了。
  • 好的,实际上这在 .net core 2 中似乎已经过时了。获得更新会很棒! :)
【解决方案3】:

如果您想将标准 .Net 角色映射与 Keycloak 客户端角色一起使用,请进行如下设置:

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 客户端设置:

  • 创建新的令牌映射器
  • Mapper-Values(输入您自己的客户名称)

现在您可以使用标准授权角色语句将您的 Keycloak 客户端角色应用于您的 ASP.NET 项目:

[Authorize(Roles = "Users")]

【讨论】:

  • 只是为了明确一点:对于 /Signout 我应该使用我的 keycloak-realm 的 logout-endpoint,不是吗?或者你是否在 /signout 下创​​建了一个资源,它在内部调用它并创建一个注销页面或其他东西?
  • 两者都行,这取决于您的要求。如果您需要拦截注销过程的任何部分,比如让用户留在您的 UI 上而不是重定向到 keycloak,那么您将创建自己的注销并实现 keycloak API 以注销。否则,keycloak 注销端点就足够了。
  • 另外要明确一点,上面的配置会检查keycloak,自动获取signout路径,并在你的应用中分配给“/SignOut”。这是 options.RemoteSignOutPath 配置设置。
  • 嘿,我在注销时遇到问题。该应用程序会自动重新对用户进行身份验证。我打电话给:do! ctx.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme)do! ctx.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme)(我使用 F# 和 Saturn)。知道有什么问题吗?退出后有什么特别需要做的吗?
【解决方案4】:

我们能否通过 .net core 5+ 获得有关此问题的最新答案?我最近安装了 keycloak 版本 13.0.0 并且它的工作允许我使用单点登录和几个应用程序。现在出于真正的原因,我安装了 keycloak,用于 webapi 身份验证。根据上面的答案,我已经安装了 Microsoft.AspNetCore.Authentication.OpenIdConnect 并一直在努力让它在 webapi 端和客户端上都能正常工作。

【讨论】:

猜你喜欢
  • 2019-10-26
  • 2018-08-12
  • 1970-01-01
  • 2017-11-28
  • 2021-01-01
  • 2023-02-04
  • 1970-01-01
  • 2023-02-17
  • 2019-04-05
相关资源
最近更新 更多