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
相关产品推荐
相关产品推荐

