注销IdentityServer4 + ASP.NET Core MVC + Angular应用程序

时间:2019-05-14 11:33:01

标签: angular cookies identityserver4 logout asp.net-core-2.2

成功注销后,我无法正确返回客户端应用程序。首先,我想描述一下我的设置。

  • IdentityServer4作为IDP
  • 2个ASP.NET Core MVC应用程序(从IS4角度来看是客户端)。 MVC应用程序使用两种身份验证方案(用于身份验证的基于“ oidc” -cookie的方案以及用于其余api调用的JWT Bearer令牌方案)
  • 2个Angular 7 SPA(由上述MVC应用托管)

因为我的项目对安全性有很高的要求,所以我使用混合流程进行授权。 因此登录流程如下:

  1. 用户未通过身份验证并访问SPA应用程序,他在其中单击登录按钮
  2. Angular应用程序重定向到[Authorize]属性下的MVC端点,从而发起OIDC挑战。
  3. 用户被OidcMiddleware重定向到IS4,在那里他可以输入用户名和密码
  4. 正在将用户重定向(成功登录后)回到MVC登录端点逻辑(在第2页中进行了调用),该逻辑负责将用户重定向回到Angular SPA。
  5. Angular对[Authorize]下的MVC端点进行http调用,并负责将IS4 JWT生成的令牌返回给客户端。
  6. 由于用户已登录到MVC客户端(存在cookie),因此MVC后端从cookie中提取了JWT令牌(access_token)并将其返回给客户端
  7. 此刻登录流程已完成(REST API的角度使用称为JWT令牌)-因此,我在后端使用了两种身份验证方案。

因此,现在我面临注销功能的一些问题。首先要描述退出流程:

  1. 已登录的用户单击角度应用程序中的“退出”按钮
  2. Spa应用程序清除本地存储条目(存储JWT令牌的位置),并将用户重定向到MVC应用程序上的注销操作。代码如下:

    [AllowAnonymous]     公共异步任务注销(字符串returnUrl)     {         等待HttpContext.SignOutAsync(“ Cookies”);         等待HttpContext.SignOutAsync(“ oidc”);     }

  3. “ oidc”方案上的SignoutAsync触发OIDC退出流程(重定向到IS4退出端点)

  4. IS4注销端点正在加载注销上下文(来自IS4快速入门的代码)

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Logout(LogoutDto dto)
    {
        // build a model so the logged out page knows what to display
        var vm = await BuildLoggedOutViewModelAsync(dto.LogoutId);
    
        if (User?.Identity.IsAuthenticated == true)
        {
            // delete local authentication cookie
            await HttpContext.SignOutAsync();
    
            // raise the logout event
            await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName()));
        }
    
        // check if we need to trigger sign-out at an upstream identity provider
        if (vm.TriggerExternalSignout)
        {
            // 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.
            string url = Url.Action("Logout", new { logoutId = vm.LogoutId });
    
            // this triggers a redirect to the external provider for sign-out
            return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme);
        }
    
        return View("LoggedOut", vm);
    }
    
  5. 重要的是BuildLoggedOutViewModelAsync方法,该方法加载注销上下文:

    私有异步任务BuildLoggedOutViewModelAsync(string logoutId)     {         //获取上下文信息(客户端名称,发布注销重定向URI和用于联合注销的iframe)         var context =等待_interaction.GetLogoutContextAsync(logoutId);

        var vm = new LoggedOutViewModel
        {
            AutomaticRedirectAfterSignOut = AccountOptions.AutomaticRedirectAfterSignOut,
            PostLogoutRedirectUri = context?.PostLogoutRedirectUri,
            ClientName = string.IsNullOrEmpty(context?.ClientName) ? context?.ClientId : context?.ClientName,
            SignOutIframeUrl = context?.SignOutIFrameUrl,
            LogoutId = logoutId
        };
    
        if (User?.Identity.IsAuthenticated == true)
        {
            var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value;
            if (idp != null && idp != IdentityServerConstants.LocalIdentityProvider)
            {
                var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp);
                if (providerSupportsSignout)
                {
                    if (vm.LogoutId == null)
                    {
                        // if there's no current logout context, we need to create one
                        // this captures necessary info from the current logged in user
                        // before we signout and redirect away to the external IdP for signout
                        vm.LogoutId = await _interaction.CreateLogoutContextAsync();
                    }
    
                    vm.ExternalAuthenticationScheme = idp;
                }
            }
        }
    
        return vm;
    }
    
  6. 这是问题所在。在我的mvc cookie过期的情况下,上下文将大多数属性设置为null,例如PostLogoutRedirectUrl。因此,我无法在IS4 LoggedOut.cshtml视图上显示“返回客户”链接。

在这种情况下,我的mvc客户端cookie没有过期(有效),一切正常。我有PostLogoutRedirectUrl,它使我可以从IS4返回到触发登出的客户端。

您有什么想法,我该如何解决?提前非常感谢您!

1 个答案:

答案 0 :(得分:0)

  1. Spa应用程序清除本地存储条目(存储JWT令牌的位置),并将用户重定向到MVC应用程序上的注销操作。

^^我认为您应该执行上述步骤。 IDS会照顾好它。