ASP.NET Core 6集成Keycloak登录成功后认证失败问题排查
我用Docker部署了本地Keycloak服务器,创建了Realm、用户、角色及客户端(仅设置凭据获取密钥,未配置映射器、客户端范围等),其他语言(PHP/Node.js)应用用类似配置可正常工作。但在ASP.NET Core MVC项目中,访问需要授权的页面触发Keycloak登录,登录成功跳转后User.Identity.IsAuthenticated始终为false,系统无法识别已认证状态。
相关配置代码如下:
认证中间件配置
services.AddAuthentication(options => { //Sets cookie authentication scheme options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie(cookie => { //Sets the cookie name and maxage, so the cookie is invalidated. cookie.Cookie.Name = "keycloak.cookie"; cookie.Cookie.MaxAge = TimeSpan.FromMinutes(60); cookie.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; cookie.SlidingExpiration = true; }) .AddOpenIdConnect(options => { //Use default signin scheme options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; //Keycloak server options.Authority = Configuration.GetSection("Keycloak")["ServerRealm"]; //Keycloak client ID options.ClientId = Configuration.GetSection("Keycloak")["ClientId"]; //Keycloak client secret options.ClientSecret = Configuration.GetSection("Keycloak")["ClientSecret"]; //Keycloak .wellknown config origin to fetch config // options.MetadataAddress = Configuration.GetSection("Keycloak")["Metadata"]; //Require keycloak to use SSL options.RequireHttpsMetadata = false; options.GetClaimsFromUserInfoEndpoint = true; options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("email"); //Save the token options.SaveTokens = true; //Token response type, will sometimes need to be changed to IdToken, depending on config. options.ResponseType = OpenIdConnectResponseType.Code; //SameSite is needed for Chrome/Firefox, as they will give http error 500 back, if not set to unspecified. options.NonceCookie.SameSite = SameSiteMode.None; options.CorrelationCookie.SameSite = SameSiteMode.None; options.TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name", RoleClaimType = "https://schemas.scopic.com/roles" }; Configuration.Bind("<Json Config Filter>", options); options.Events.OnRedirectToIdentityProvider = async context => { context.ProtocolMessage.RedirectUri = "http://localhost:13636/home"; await Task.FromResult(0); }; });
中间件顺序配置
app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization();
HomeController代码
public class HomeController : Controller { private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; } public IActionResult Index() { bool value = User.Identity.IsAuthenticated; return View(); } [Authorize] public IActionResult Privacy() { return View(); } }
修复方案
1. 修正OIDC回调地址逻辑
移除OnRedirectToIdentityProvider事件中硬编码的RedirectUri:
// 删除这段代码 // options.Events.OnRedirectToIdentityProvider = async context => // { // context.ProtocolMessage.RedirectUri = "http://localhost:13636/home"; // await Task.FromResult(0); // };
OIDC中间件默认使用/signin-oidc作为回调端点,这个路径是中间件内置处理认证响应、生成认证Cookie的核心路径。硬编码其他地址会导致Keycloak回调后无法触发认证流程的收尾逻辑。
同时在Keycloak客户端的Valid Redirect URIs中添加http://localhost:13636/signin-oidc,确保Keycloak允许回调到该地址。
2. 修复Configuration.Bind占位符
将Configuration.Bind("<Json Config Filter>", options);中的<Json Config Filter>替换为实际的配置节点名称(例如"Keycloak:Oidc",对应appsettings.json中的配置结构),如果没有额外的JSON配置,直接删除该行代码,避免覆盖之前的正确配置。
3. 匹配Keycloak角色声明类型
Keycloak默认的角色声明路径是realm_access.roles,如果未在Keycloak中配置自定义映射,需要修改TokenValidationParameters:
options.TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name", RoleClaimType = "realm_access.roles" // 改为Keycloak默认的角色声明路径 };
若要保留自定义RoleClaimType,需在Keycloak客户端添加映射器,将realm_access.roles映射到https://schemas.scopic.com/roles。
4. 完善中间件路由配置
确保控制器路由配置在UseAuthorization之后,保证认证授权逻辑先于路由执行:
app.UseAuthentication(); app.UseAuthorization(); // 添加控制器路由配置 app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
5. 检查Keycloak客户端基础配置
- 确认客户端Access Type设置为
confidential(因为使用了ClientSecret) - 确保Valid Redirect URIs包含
http://localhost:13636/*或具体的回调/跳转地址 - 验证Standard Flow Enabled已启用(对应
Code响应类型的授权流程)
修改完成后重启ASP.NET Core应用,再次测试登录流程,User.Identity.IsAuthenticated即可正确识别认证状态。
内容的提问来源于stack exchange,提问作者James Bond

