ASP.NET Core 的 Keycloak 客户端
Posted
技术标签:
【中文标题】ASP.NET Core 的 Keycloak 客户端【英文标题】:Keycloak client for ASP.NET Core 【发布时间】: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 【参考方案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 客户端配置如下:
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如果我想按角色授权用户,我会这样做:
在 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 端和客户端上都能正常工作。
【讨论】:
你可以尝试使用这个库github.com/lvermeulen/Keycloak.Net以上是关于ASP.NET Core 的 Keycloak 客户端的主要内容,如果未能解决你的问题,请参考以下文章