Search code examples
c#asp.net-coreidentityserver4

How to redirect user to client app after logging out from identity server?


I want to redirect user to the same client after he logged out from that client. So if i have lets say 5 clients on one identity server, i want users to be able to log out from one client and be on that same client but logged out.

The one thing i have tried is to use PostLogoutRedirectUri in AccountController in quickstart, but the value is always null. Workaround that i found is to manually set PostLogoutRedirectUri, that works fine if you have only one client on the server, but not so much if I have multiple. Is there any way to know which client has been "logged out"?

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

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


        vm.PostLogoutRedirectUri = "http://localhost:56582";
        return Redirect(vm.PostLogoutRedirectUri);
    }

My Client

 new Client
                {

                    ClientId =  "openIdConnectClient",
                    ClientName = "Implicit Client Application Name",
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.Email,
                        "role",
                        "customAPI.write"
                    },

                    RedirectUris = new List<string>{ "http://localhost:56582/signin-oidc" },
                    PostLogoutRedirectUris = new List<string>{ "http://localhost:56582" },
                   // FrontChannelLogoutUri = "http://localhost:56582/signout-oidc"

                }

Solution

  • You are not supposed to set the uri manually. Actually the default logout method from the IdentityServer samples works fine.

    When you try the 3_ImplicitFlowAuthentication sample project, you'll see PostLogoutRedirectUri is not null and the redirection works (but not automatically).

    The reason why PostLogoutRedirectUri is null in your case is probably because the id_token is not preserved. In MvcClient.Startup make sure you add this line:

    options.SaveTokens = true;
    

    That will preserve the tokens in a cookie.

    In order to automatically redirect back to the client, make a few adjustments to the sample code. In IdentityServer AccountOptions set

    AutomaticRedirectAfterSignOut = true;
    

    In the AccountController.Logout method add the following lines:

    if (vm.AutomaticRedirectAfterSignOut && 
                   !string.IsNullOrWhiteSpace(vm.PostLogoutRedirectUri))
        return Redirect(vm.PostLogoutRedirectUri);
    

    Just before the last line:

    return View("LoggedOut", vm);
    

    When you run the sample again you should see that the user is now automatically returned to the client after logout.