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

OpenIddict/OIDC登出流程陷入无限循环问题排查

登出无限循环问题排查与修复

核心问题分析

  • 客户端认证配置中,DefaultSignOutScheme指定为OpenIddict服务器Scheme,同时登出方法重复调用该Scheme的SignOut,导致登出流程被循环触发。
  • 认证服务器的Logout方法错误使用OpenIddictServerAspNetCoreDefaults.AuthenticationScheme执行SignOut,这会再次触发登出流程,而非完成登出后跳转。
  • 客户端登出时的RedirectUri与SignedOutRedirectUri设置冲突,导致跳转逻辑混乱。

具体修复步骤

1. 调整客户端应用Startup.cs认证配置

修改默认登出Scheme为Cookie认证,避免默认登出直接触发OpenIddict流程:

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIddictServerAspNetCoreDefaults.AuthenticationScheme;
    // 修改默认登出Scheme为Cookie认证
    options.DefaultSignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, options =>
{
    options.SignInScheme = IdentityConstants.ApplicationScheme;
    options.Authority = "https://localhost:44395";
    options.ClientId = "myclient";
    options.ResponseType = OpenIdConnectResponseType.Code;
    options.Scope.Add(Scopes.Profile);
    options.Scope.Add(Scopes.Email);
    options.CallbackPath = "/signin-oidc";
    options.SaveTokens = true;
    options.TokenValidationParameters = new TokenValidationParameters
    {
        NameClaimType = Claims.Name
    };
    options.GetClaimsFromUserInfoEndpoint = true;
    // 移除冲突的SignedOutRedirectUri,让OpenIddict自动使用post_logout_redirect_uri
});

2. 修改客户端应用AccountController的Logout()方法

同时清除本地Cookie并触发OpenIddict登出流程,无需手动指定跳转地址:

[HttpPost, ValidateAntiForgeryToken]
public async Task<IActionResult> Logout()
{
    // 清除本地Identity会话Cookie
    await _signInManager.SignOutAsync();
    // 触发OpenIddict全局登出流程
    return SignOut(
        authenticationSchemes: new[] {
            CookieAuthenticationDefaults.AuthenticationScheme,
            OpenIddictServerAspNetCoreDefaults.AuthenticationScheme
        });
}

3. 修复认证服务器AuthorizationController的Logout()方法

仅清除本地Identity Cookie,根据请求参数完成跳转,避免重复触发登出:

[HttpGet("~/connect/logout")]
public async Task<IActionResult> Logout()
{
    // 清除认证服务器的用户会话Cookie
    await _signInManager.SignOutAsync();
    
    // 获取客户端传递的post_logout_redirect_uri,验证后跳转
    var postLogoutUri = Request.Query["post_logout_redirect_uri"].ToString();
    if (!string.IsNullOrEmpty(postLogoutUri) && Url.IsLocalUrl(postLogoutUri))
    {
        return Redirect(postLogoutUri);
    }
    
    // 无有效跳转地址时,默认跳转到认证服务器登录页
    return Redirect("/Account/Login");
}

4. 确认客户端post_logout_redirect_uri已注册

确保认证服务器的客户端配置中,myclient的post_logout_redirect_uri已正确设置为http://localhost:5000/signout-callback-oidc,防止跳转被拦截。

修复原理

  • 客户端登出时先清理本地会话,再触发OpenIddict标准登出流程,让认证服务器处理全局会话销毁。
  • 认证服务器登出后根据客户端传递的合法跳转地址完成跳转,避免循环触发登出逻辑。
  • 移除冲突的跳转配置,严格遵循OpenID Connect登出规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 11:20:55