Duende IdentityServer:RP登出跳转后无认证用户,联邦登出失效
问题:Duende IdentityServer联邦登出时无已认证用户导致外部登出失效
我正在遵循Duende IdentityServer的第2个快速入门教程,已完成IdentityServer和依赖方(RP)Web应用的创建,登录、登出功能正常。添加外部登录提供商后登录正常,但想要实现联邦登出(从RP登出时同时退出IdentityServer和外部提供商)时遇到问题:
当从RP登出并跳转到IdentityServer的Logout/Index.cshtml.cs的OnGet方法时,始终不存在已认证用户,导致showLogoutPrompt一直为false,直接调用OnPost(),而处理联邦登出的代码因为没有已认证用户永远不会执行。
RP的SignOut.cshtml.cs代码
public class SignOutModel : PageModel { public IActionResult OnGet() { return SignOut("Cookies", "oidc"); } }
IdentityServer的Logout/Index.cshtml.cs OnGet方法
public async Task<IActionResult> OnGet(string? logoutId) { LogoutId = logoutId; var showLogoutPrompt = LogoutOptions.ShowLogoutPrompt; if (User.Identity?.IsAuthenticated != true) // 此处始终为false { // if the user is not authenticated, then just show logged out page showLogoutPrompt = false; } else { var context = await _interaction.GetLogoutContextAsync(LogoutId); if (context?.ShowSignoutPrompt == false) { // it's safe to automatically sign-out showLogoutPrompt = false; } } if (showLogoutPrompt == false) { // if the request for logout was properly authenticated from IdentityServer, then // we don't need to show the prompt and can just log the user out directly. return await OnPost(); } return Page(); }
IdentityServer的Logout/Index.cshtml.cs OnPost方法
public async Task<IActionResult> OnPost() { if (User.Identity?.IsAuthenticated == true) // 此处始终为false { // if there's no current logout context, we need to create one // this captures necessary info from the current logged in user // this can still return null if there is no context needed LogoutId ??= await _interaction.CreateLogoutContextAsync(); // delete local authentication cookie await HttpContext.SignOutAsync(); // see if we need to trigger federated logout var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value; // raise the logout event await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName())); Telemetry.Metrics.UserLogout(idp); // if it's a local login we can ignore this workflow if (idp != null && idp != Duende.IdentityServer.IdentityServerConstants.LocalIdentityProvider) { // we need to see if the provider supports external logout if (await HttpContext.GetSchemeSupportsSignOutAsync(idp)) { // build a return URL so the upstream provider will redirect back // to us after the user has logged out. this allows us to then // complete our single sign-out processing. var url = Url.Page("/Account/Logout/Loggedout", new { logoutId = LogoutId }); // this triggers a redirect to the external provider for sign-out return SignOut(new AuthenticationProperties { RedirectUri = url }, idp); } } } return RedirectToPage("/Account/Logout/LoggedOut", new { logoutId = LogoutId }); }
我想知道为什么始终没有已认证用户?是不是RP调用SignOut("Cookies","oidc")时,在跳转到IdentityServer之前就移除了会话Cookie?我认为RP无法删除IdP的会话Cookie(因为属于不同域),但可能我错了。另外,请求/connect/endsession中并不包含该Cookie。
我严格遵循了快速入门教程,这种行为是有意设计的吗?
内容的提问来源于stack exchange,提问作者jbol
相关产品推荐
相关产品推荐

