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

ASP.NET Core集成Keycloak OpenID Connect:登出后重登免验证问题

问题描述

基于ASP.NET Core的Web应用通过Keycloak OpenID Connect实现身份认证,Keycloak客户端已配置支持标准流与隐式流,并指定了有效重定向URI。应用启动后可正常跳转至Keycloak登录页面,登录后能重定向回应用;点击登出按钮后,应用Cookie已清除,但再次点击登录按钮时,未触发Keycloak登录验证,直接返回应用主页。通过Fiddler观察到请求已抵达Keycloak服务器,且服务器已颁发新令牌,推测问题源于Keycloak配置或应用登出逻辑缺失。

相关代码如下:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
                {
                    // Store the session to cookies
                    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    // OpenId authentication
                    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
                })
                .AddCookie(cookie =>
                {
                    cookie.Cookie.Name = "keycloak.cookie";
                    cookie.Cookie.MaxAge = TimeSpan.FromMinutes(60);
                    cookie.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
                    cookie.SlidingExpiration = true;
                })
                .AddOpenIdConnect(options =>
                {
                    
                    options.Authority = Configuration.GetSection("Keycloak")["Authority"];
                    //Keycloak client ID
                    options.ClientId = Configuration.GetSection("Keycloak")["ClientId"];
                    //Keycloak client secret
                    options.ClientSecret = Configuration.GetSection("Keycloak")["ClientSecret"];
                    
                    // For testing we disable https (should be true for production)
                    options.RequireHttpsMetadata = false;
                    options.SaveTokens = true;
                    options.GetClaimsFromUserInfoEndpoint = true;
                    // OpenID flow to use
                    options.ResponseType = OpenIdConnectResponseType.CodeIdToken;

                });

}

index.cshtml

@if(User.Identity.IsAuthenticated)
{
<form class="form-inline" asp-page="/Index" asp-page-handler="Logout">
                                    <button type="submit" class="nav-link btn btn-link text-light">Sign out</button>
                                </form>
} else{
<a class="nav-link text-light" asp-page="/Index">Sign in</a>
}

Index.cshtml.cs

public void OnGet(){...}
public async Task<IActionResult> OpPostLogout(){
  Console.WriteLine("Logging out...");
  await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
  Console.WriteLine("Signed out of Cookie Authentication!");
            
  await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);            
            
  Console.WriteLine("Signed out of OpenIDConnect!");
  return RedirectToPage("./Logout");
}
解决方案

核心问题是:登出仅清除了应用端Cookie,但Keycloak服务器上的用户会话仍处于活跃状态,再次认证时Keycloak复用已有会话直接颁发令牌,跳过登录页面验证。需从应用代码和Keycloak配置两方面修复:

1. 完善ASP.NET Core登出逻辑

当前代码仅清除本地Cookie和OIDC会话,未触发Keycloak的全局登出。修改登出方法,引导用户到Keycloak登出端点清除服务器端会话:

public async Task<IActionResult> OnPostLogout()
{
    // 清除应用本地Cookie
    await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    
    // 构建Keycloak登出请求,指定回调地址
    var openIdOptions = HttpContext.RequestServices.GetRequiredService<IOptionsMonitor<OpenIdConnectOptions>>().Get(OpenIdConnectDefaults.AuthenticationScheme);
    var logoutBaseUrl = $"{openIdOptions.Authority}/protocol/openid-connect/logout";
    var redirectUri = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}/Logout";
    
    var logoutUrl = $"{logoutBaseUrl}?client_id={openIdOptions.ClientId}&redirect_uri={Uri.EscapeDataString(redirectUri)}";
    
    return Redirect(logoutUrl);
}

同时在Startup.cs的OpenID Connect配置中添加回调路径:

options.SignedOutCallbackPath = "/Logout";

2. 配置Keycloak客户端登出参数

登录Keycloak管理控制台,找到目标客户端:

  • 在Settings标签页,在Valid Redirect URIs下方添加登出回调地址(如http://localhost:5000/Logout,需与应用中redirectUri一致)
  • 在Advanced标签页的Access Settings中,将Logout Redirect URIs设置为相同的回调地址
  • 开启Frontchannel Logout,并设置Frontchannel Logout URI为应用登出回调地址(确保Keycloak主动通知应用失效会话)

3. 强制每次认证显示登录页面(可选)

若需每次登录都强制验证,即使Keycloak有活跃会话,可在认证请求中添加prompt=login参数:

在Startup.cs的OpenID Connect配置中添加事件:

options.Events = new OpenIdConnectEvents
{
    OnRedirectToIdentityProvider = context =>
    {
        context.ProtocolMessage.Prompt = "login";
        return Task.CompletedTask;
    }
};

配置完成后,用户登出时会先清除应用Cookie,再跳转到Keycloak清除服务器端会话,再次登录时Keycloak无活跃会话,将触发登录页面验证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 17:45:29