IdentityServer 显示空白 PostLogoutRedirectUri for Android Native App

问题描述

我使用 IdentityServer4 和 .Net Core Signin Manager 创建了一个 OAuth 服务器。登录效果很好并返回到我的应用程序。注销似乎不知道谁在注销。退出 Razor 页面代码如下:

   public async Task<IActionResult> OnGet(string logoutId)
    {

        var logout = await _interaction.GetlogoutContextAsync(logoutId);

        PostlogoutRedirectUri = logout?.PostlogoutRedirectUri;
        AutomaticRedirectAfterSignOut = (PostlogoutRedirectUri != null);
        ClientName = string.IsNullOrEmpty(logout?.ClientName) ? logout?.ClientId : logout?.ClientName;
        SignOutIframeUrl = logout?.SignOutIFrameUrl;
        logoutId = logoutId;

        if (User?.Identity.IsAuthenticated == true)
        {
            var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value;
            if (idp != null && idp != IdentityServer4.IdentityServerConstants.LocalIdentityProvider)
            {
                var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp);
                if (providerSupportsSignout)
                {
                    if (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
                        logoutId = await _interaction.CreatelogoutContextAsync();
                    }

                    ExternalAuthenticationScheme = idp;
                }
            }

            // delete local authentication cookie
            await _signInManager.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 (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 = logoutId });

            // this triggers a redirect to the external provider for sign-out
            return SignOut(new AuthenticationProperties { RedirectUri = url },ExternalAuthenticationScheme);
        }

        if (AutomaticRedirectAfterSignOut)
            return Redirect(PostlogoutRedirectUri);
        else
            return Page();
    }

当它被调用时,有一个 logoutId。它获取上下文,但 PostlogoutRedirectUri 为空。 ClientId 和 ClientName 也为空,但上下文有一个名为 ClientIds 的字段,第一个条目是我的应用程序的正确 ClientId。日志显示如下:

IdentityServer4.Validation.EndSessionRequestValidator: information: End session request validation success
{
  "SubjectId": "6841dc6c-0bd7-4f72-8f1c-f7czzzzzzzzz","Raw": {
    "post_logout_redirect_uri": "mps.mobile.app://callback"
  }
}
IdentityServer4.Hosting.IdentityServerMiddleware: information: Invoking IdentityServer endpoint: IdentityServer4.Endpoints.EndSessionCallbackEndpoint for /connect/endsession/callback
IdentityServer4.Endpoints.EndSessionCallbackEndpoint: information: Successful signout callback.

我正在为客户端应用程序使用 IdentityModel。我的注销编码如下:

        _options = new OidcclientOptions
        {
            Authority = MPSOidc.Authority,ClientId = MPSOidc.ClientID,Scope = "openid profile myapi offline_access email",RedirectUri = MPSOidc.RedirectUri,PostlogoutRedirectUri = MPSOidc.RedirectUri,ResponseMode = OidcclientOptions.AuthorizeResponseMode.Redirect,browser = new ChromeCustomTabsbrowser(this)
        };

        var oidcclient = new Oidcclient(_options);

        var r = new logoutRequest();

        await oidcclient.logoutAsync(r);

似乎 PostlogoutRedirectUri 应该出现在这里。有谁知道一种方法来实现这一目标?如果没有,是否可以通过ClientId 获取Client 信息以找到其中的PostlogoutRedirectUri?

谢谢, 吉姆

解决方法

原来是这样。当我在 OidcClient 上注销时,我没有传递 ID 令牌。在我的客户端 Android 应用程序上,我必须将 ID 令牌添加到注销请求中:

          var r = new LogoutRequest()
            {
                IdTokenHint = MPSOidc.Tokens.IdentityToken
            };

这就是全部。 干杯。