You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET集成Keycloak登录成功后IsAuthenticated始终为false

问题分析与解决方案

你遇到的User.Identity.IsAuthenticated始终为false的问题,核心原因是OpenIdConnect中间件未将Keycloak返回的认证信息写入Cookie,导致后续请求无法识别已认证身份,进而引发循环重定向。以下是具体修正方案:

关键配置缺失点

  1. 未关联Cookie认证类型:原OpenIdConnect配置中未指定SignInAsAuthenticationType,导致登录后的身份信息无法持久化到Cookie中。
  2. 缺少令牌交换与身份生成逻辑:仅配置基础参数后,ASP.NET不会自动处理Keycloak返回的授权码,无法生成有效的ClaimsIdentity。

修改后的完整配置代码

const string persistentAuthType = "keycloak_auth";

app.SetDefaultSignInAsAuthenticationType(persistentAuthType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = persistentAuthType,
    SlidingExpiration = true,
    ExpireTimeSpan = TimeSpan.FromMinutes(30) // 设置Cookie过期时间
});

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    AuthenticationType = "keycloak_auth",
    ClientId = clientId,
    Authority = authorityserver,
    RedirectUri = "http://localhost:13636/home",
    PostLogoutRedirectUri = "http://localhost:13636",
    ClientSecret = clientSecret,
    RequireHttpsMetadata = false,
    ResponseType = OpenIdConnectResponseType.Code,
    Scope = "openid profile email",
    
    // 核心:指定登录后使用的Cookie认证类型
    SignInAsAuthenticationType = persistentAuthType,
    
    // 配置令牌验证规则
    TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidIssuer = authorityserver,
        ValidateAudience = true,
        ValidAudience = clientId,
        ValidateLifetime = true
    },
    
    // 处理授权码交换与身份生成
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        AuthorizationCodeReceived = async n =>
        {
            // 用授权码交换访问令牌和刷新令牌
            var tokenClient = new HttpClient();
            var tokenResponse = await tokenClient.PostAsync(
                $"{authorityserver}/protocol/openid-connect/token",
                new FormUrlEncodedContent(new Dictionary<string, string>
                {
                    ["grant_type"] = "authorization_code",
                    ["client_id"] = clientId,
                    ["client_secret"] = clientSecret,
                    ["code"] = n.Code,
                    ["redirect_uri"] = "http://localhost:13636/home"
                })
            );

            if (!tokenResponse.IsSuccessStatusCode)
                throw new Exception("授权码交换令牌失败");

            var tokenContent = await tokenResponse.Content.ReadAsStringAsync();
            var tokens = JsonConvert.DeserializeObject<dynamic>(tokenContent);

            // 获取用户信息
            var userInfoClient = new HttpClient();
            var userInfoResponse = await userInfoClient.GetAsync(
                $"{authorityserver}/protocol/openid-connect/userinfo?access_token={tokens.access_token}"
            );
            var userInfo = await userInfoResponse.Content.ReadAsStringAsync();

            // 构建包含用户声明的身份对象
            var identity = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
            identity.AddClaims(n.AuthenticationTicket.Identity.Claims);
            identity.AddClaim(new Claim("access_token", tokens.access_token));
            identity.AddClaim(new Claim("refresh_token", tokens.refresh_token));

            // 添加用户信息中的自定义声明
            var userClaims = JsonConvert.DeserializeObject<Dictionary<string, object>>(userInfo);
            foreach (var claim in userClaims)
            {
                identity.AddClaim(new Claim(claim.Key, claim.Value.ToString()));
            }

            // 更新认证票据
            n.AuthenticationTicket = new AuthenticationTicket(
                new ClaimsIdentity(identity.Claims, n.AuthenticationTicket.Identity.AuthenticationType),
                n.AuthenticationTicket.Properties
            );
        }
    }
});

简化控制器认证判断

可以替换手动判断逻辑,使用ASP.NET内置的[Authorize]特性自动处理未认证请求:

[Authorize(AuthenticationTypes = "keycloak_auth")]
public class HomeController : BaseController
{
    public ActionResult Index()
    {
        ViewBag.Title = "Home";
        return View();
    }
}

验证要点

  1. 确保Keycloak客户端配置中的Valid Redirect URIs包含http://localhost:13636/home。
  2. 检查是否引用了Microsoft.Owin.Security.OpenIdConnect和Newtonsoft.Json包(用于令牌解析)。

内容的提问来源于stack exchange,提问作者user2300947

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 04:10:12