0

I have created an OAuth Server using IdentityServer4 and .Net Core Signin Manager. The Login works great and returns to my app. The Logout doesn't seem to know who is logging out. The Logout Razor Page code is as follows:

   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();
    }

When it gets called, there is a logoutId. It gets the context, but PostLogoutRedirectUri is blank. ClientId and ClientName are also blank, but the context has a field called ClientIds and the first entry is the correct ClientId for my app. The log shows as follows:

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.

I am using IdentityModel for the Client App. I have the logout coded as follows:

        _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);

It seems like the PostLogoutRedirectUri should show up here. Does anyone know a way to make this happen? If not, can the ClientId be used to get the Client information to find the PostLogoutRedirectUri there?

Thanks, Jim

Jim Wilcox
  • 1,480
  • 16
  • 33

1 Answers1

1

Here is what it was. When I logged out on the OidcClient, I didn't pass the ID Token. On my client Android app, I had to add the ID Token to the logout request:

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

That's all it took. Cheers.

Jim Wilcox
  • 1,480
  • 16
  • 33