Identityserver4: PostLogoutRedirectUri from LogoutContext always null

Created on 28 Mar 2017  路  13Comments  路  Source: IdentityServer/IdentityServer4

In my client app in startup.auth.cs

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                AuthenticationType = "oidc",
                ClientId = Clients.FORMATION,
                SignInAsAuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                Authority = ConfigurationManager.AppSettings["Authority"],
                RedirectUri = ConfigurationManager.AppSettings["RedirectUri"], // http://fedecp.local
                **PostLogoutRedirectUri = ConfigurationManager.AppSettings["PostLogoutUri"],**
                ClientSecret = "secret", // TODO
                ResponseType = "code id_token",
                Scope = "openid profile offline_access",
                RefreshOnIssuerKeyNotFound = true
            });

In my IndetityServer project

new Client
                {
                    ClientId = Clients.FORMATION,
                    ClientName = "FEDECP Formation MVC Client",
                    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
                    RequireConsent = false,
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256()) // TODO
                    },

                    RedirectUris = redirectUris,
                    PostLogoutRedirectUris = postLogoutRedirectUris, // ["http://fedecp.local"]
                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.OfflineAccess,
                        ApiResources.SSO
                        //"some other api",
                    },
                    AllowAccessTokensViaBrowser = false,
                    AlwaysIncludeUserClaimsInIdToken = true,
                    AllowOfflineAccess = true // Specifies whether this client can request refresh tokens (by requesting the offline_access scope)
                },

I started my project based on one of your samples.
In the AccountService class -> BuildLoggedOutViewModelAsync(string logoutId)
var logout = await _interaction.GetLogoutContextAsync(logoutId);

In the logout object PostLogoutRedirectUri attribute is always null

Here are the logs

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://id.fedecp.local:9000/connect/endsession?post_logout_redirect_uri=http%3a%2f%2ffedecp.local
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[3]
      HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Identity.Application.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Request path /connect/endsession matched to endpoint type EndSession
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Mapping found for endpoint: EndSession, creating handler: IdentityServer4.Endpoints.EndSessionEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.EndSessionEndpoint for /connect/endsession
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
dbug: IdentityServer4.Endpoints.EndSessionEndpoint[0]
      Processing signout request for A186C135-0D2E-4BE6-A116-8E397B339C6D
dbug: IdentityServer4.Validation.EndSessionRequestValidator[0]
      Start end session request validation
info: IdentityServer4.Validation.EndSessionRequestValidator[0]
      End session request validation success
      {
        "SubjectId": "unknown",
        "Raw": {
          "post_logout_redirect_uri": "http://fedecp.local"
        }
      }
dbug: IdentityServer4.Endpoints.EndSessionEndpoint[0]
      Success validating end session request from (null)
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 73.562ms 302
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://id.fedecp.local:9000/account/logout?logoutId=5bf382b6289eec963f71a966a4431c93
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[3]
      HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Identity.Application.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method Fedecp.Identity.Server.Web.Controllers.AccountController.Logout (Fedecp.Identity.Server.Web) with arguments (5bf382b6289eec963f71a966a4431c93) - ModelState is Valid
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
info: Fedecp.Identity.Server.Web.Controllers.AccountController[0]
      geeks logout.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[8]
      AuthenticationScheme: Identity.Application was successfully authenticated.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[11]
      AuthenticationScheme: Identity.Application signed out.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[11]
      AuthenticationScheme: Identity.External signed out.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[11]
      AuthenticationScheme: Identity.TwoFactorUserId signed out.
info: Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewResultExecutor[1]
      Executing ViewResult, running view at path /Views/Account/LoggedOut.cshtml.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action Fedecp.Identity.Server.Web.Controllers.AccountController.Logout (Fedecp.Identity.Server.Web) in 85774.3312ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 85789.3811ms 200 text/html; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://id.fedecp.local:9000/connect/endsession/callback?sid=27dd6dddd525cb7540ed938648f85719&logoutId=5bf382b6289eec963f71a966a4431c93
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Request path /connect/endsession/callback matched to endpoint type EndSession
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Mapping found for endpoint: EndSession, creating handler: IdentityServer4.Endpoints.EndSessionEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.EndSessionEndpoint for /connect/endsession/callback
dbug: IdentityServer4.Endpoints.EndSessionEndpoint[0]
      Processing signout callback request
dbug: IdentityServer4.Validation.EndSessionRequestValidator[0]
      No client end session iframe URLs
info: IdentityServer4.Endpoints.EndSessionEndpoint[0]
      Successful signout callback. Client logout iframe urls:
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 33.6936ms 200 text/html; charset=UTF-8
question

Most helpful comment

@oakdemirci
I got it working using this snippet of code (the notification part) using using Microsoft.Owin.Security.OpenIdConnect

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                AuthenticationType = "oidc",
                ClientId = Clients.FORMATION,
                SignInAsAuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                Authority = ConfigurationManager.AppSettings["Authority"],
                RedirectUri = ConfigurationManager.AppSettings["RedirectUri"],
                PostLogoutRedirectUri = ConfigurationManager.AppSettings["PostLogoutUri"],
                ClientSecret = "secret", // TODO
                ResponseType = "code id_token",
                Scope = "openid profile offline_access",

                RefreshOnIssuerKeyNotFound = true,
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = n =>
                    {
                        var id = n.AuthenticationTicket.Identity;

                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        n.AuthenticationTicket = new AuthenticationTicket(
                               id,
                               n.AuthenticationTicket.Properties);
                        return Task.FromResult(0);
                    },


                    RedirectToIdentityProvider = n =>
                    {
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token").Value;
                            n.ProtocolMessage.IdTokenHint = idTokenHint;
                        }
                        return Task.FromResult(0);
                    }

                }

            });

All 13 comments

I suspect it's related to: "SubjectId": "unknown",

How do I set a value to SubjectId ?

This is the logged in user. So I suspect the user is no longer logged into IdentityServer?

This is my logout method.
I see there is a RedirectUri member available in the authenticationProperties; Should I set it to me desired redirect URI ?
public void Logout() { _authManager.SignOut(new AuthenticationProperties()); }

I'd suggest starting with our working samples to understand how it should work.

My MVC Client is not in .Net Core. So I am not using Microsoft.AspNetCore.Authentication.OpenIdConnect this package. I am using Microsoft.Owin.Security.OpenIdConnect and Microsoft.Owin.Security.OpenIdConnect does not seem to set anything else then the redirectUri.

Have you ever seen something like this ?

@lemieuxs can you share some info/code if you got it worked?
I can not signout also in "core IdentityServer4 server" and "client MVC non core" configuration.
endsession endpoint is not being called in my case.
regards.

@lemieuxs all set -- can we close this?

@oakdemirci
I got it working using this snippet of code (the notification part) using using Microsoft.Owin.Security.OpenIdConnect

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                AuthenticationType = "oidc",
                ClientId = Clients.FORMATION,
                SignInAsAuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                Authority = ConfigurationManager.AppSettings["Authority"],
                RedirectUri = ConfigurationManager.AppSettings["RedirectUri"],
                PostLogoutRedirectUri = ConfigurationManager.AppSettings["PostLogoutUri"],
                ClientSecret = "secret", // TODO
                ResponseType = "code id_token",
                Scope = "openid profile offline_access",

                RefreshOnIssuerKeyNotFound = true,
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = n =>
                    {
                        var id = n.AuthenticationTicket.Identity;

                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        n.AuthenticationTicket = new AuthenticationTicket(
                               id,
                               n.AuthenticationTicket.Properties);
                        return Task.FromResult(0);
                    },


                    RedirectToIdentityProvider = n =>
                    {
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token").Value;
                            n.ProtocolMessage.IdTokenHint = idTokenHint;
                        }
                        return Task.FromResult(0);
                    }

                }

            });

This is so weird, I have the example and I can see the n.ProtocolMessage.PostLogoutRedirectUri is set appropriately, however it's null in IDS

return Redirect(logoutRequest.PostLogoutRedirectUri);

how can I go about troubleshooting this? Very weird :/

logs just say that param can't be null, which I think we all agree with :)

I have resolved this by adding

[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Logout(LogoutInputModel model)
        {
            // build a model so the logged out page knows what to display
            var vm = await BuildLoggedOutViewModelAsync(model.LogoutId).ConfigureAwait(false);

            if (User?.Identity.IsAuthenticated == true)
            {
                // delete authentication cookie
                await HttpContext.SignOutAsync().ConfigureAwait(false);
                // delete local authentication cookie

                await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme).ConfigureAwait(false);

                // set this so UI rendering sees an anonymous user
                HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity());

            }

......

And in MVC Client Application,
Add Logout Action Method

 public IActionResult Logout()
        {
         return   SignOut("Cookies", "oidc");

        }

Add In startup.cs

.AddOpenIdConnect("oidc", options =>
                {
   options.SignedOutCallbackPath = "your logout url";
....

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings