6

I have a similar issue to https://github.com/IdentityServer/IdentityServer4/issues/3153

I'm using the Asp Net Identity and the EF Core combined sample, everything works correctly, database, seeding, api call except for when I try to log out from the IS page. It does not delete the .AspNetCore.Cookies which is the one keeping the user logged in on the client.

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

        if (User?.Identity.IsAuthenticated == true)
        {
            _log.LogCustomInfo(LoggingType.Information, "<AUDIT>" + "Logout: User Is Authenticated" + "</AUDIT>");

            try
            {
                await _signInManager.SignOutAsync();
                await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme);
                await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
                // raise the logout event
                await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName()));
            }
            catch (NotSupportedException)
            {
                _log.LogCustomInfo(LoggingType.Information, "<AUDIT>" + "Logout: SignOutAsync Not Supported" + "</AUDIT>");
            }

        }

        /* https://github.com/IdentityServer/IdentityServer4/issues/855 */
        // check if we need to trigger sign-out at an upstream identity provider

        // delete local authentication cookie
        Response.Cookies.Delete(".AspNetCore.Identity.Application");
        Response.Cookies.Delete("idserv.external");
        Response.Cookies.Delete("idserv.session");


        _log.LogCustomInfo(LoggingType.Information, "<AUDIT>" + "Logout: Trigger external signout " + vm.TriggerExternalSignout +  "</AUDIT>");

        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 });
            //url = _configuration["AppSettings:PostLogoutRedirectUri"]; 
            url = vm.PostLogoutRedirectUri;
            //url = "redirect.html";
                                            // this triggers a redirect to the external provider for sign-out
            _log.LogCustomInfo(LoggingType.Information, "<AUDIT>" + "Logout: Redirect to " + url +  "</AUDIT>");

            return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme);
        }

        return View("LoggedOut", vm);
    }

I have the same issue from the angular client and the MVC application.

If I manually delete .AspNetCore.Identity.Application the client is logged out. I am authenticating with keycloak and using

    options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
    options.SignOutScheme = IdentityServerConstants.SignoutScheme;

In the startup IS configuration options.

George C.
  • 6,574
  • 12
  • 55
  • 80
John Bowyer
  • 1,213
  • 1
  • 15
  • 26

4 Answers4

3

I know this is an old Question, but I just had this same issue.

It turns out that the code I got from a repo didn't have the lines to delete the cookies that the Question does. Once I added it, logging out actually logged out.

Response.Cookies.Delete(".AspNetCore.Identity.Application");
Response.Cookies.Delete("idserv.external");
Response.Cookies.Delete("idserv.session");

The repo was for the current latest IdentityServer4 4.1.1 and was supposed to be working as it was the result of a walkthrough.

computercarguy
  • 2,173
  • 1
  • 13
  • 27
  • I'm running those exact lines but the stupid cookies are still there. Just refusing to get lost! Could you post a link to the source of your work-around, please? And feel free to suggest what more needs to be done to make the lines actually remove the stuff from the broswer. – Konrad Viltersten Sep 25 '21 at 12:42
  • @KonradViltersten, I'm not able to access that codebase anymore, as I've switched jobs. I wish I could help out more, but without that code, I'd just be guessing. I also don't know which public repo or walkthrough I used, since I went through at least 5 before I got things working, and that was 10 months ago, too. Sorry. – computercarguy Sep 25 '21 at 18:32
2

I was able to logout by manually deleting the application cookie. I had a problem deleting it at first because I was not specifying the application path. After I specify the cookie path, I can delete the cookie.

  Response.Cookies.Delete(".AspNetCore.Identity.Application", new CookieOptions()
    {
        Path = "/eds-daas"
    });
John Bowyer
  • 1,213
  • 1
  • 15
  • 26
1

The application Cookie should be deleted by the client application.

If you initiate the logout in your application you have to signout from both schemes, Cookies and oidc. For example:

public IActionResult Logout()
{
    return SignOut(new[] { "Cookies", "oidc" });
}

This way you already have deleted the client's cookie.

If you initiate the logout in your Idp you can use a global signout mechanism using one of these specifications:

This way you can signout from all application clients you are signed in in that moment with the same session.

All of them are supported by identity server 4.

Alpha75
  • 2,140
  • 1
  • 26
  • 49
  • This is not working for me. I need the signout to work with a redirect url. If I make the following changes to my SignOut call the .AspNetCore.Identity.Application cookie is still not deleted. return SignOut(new AuthenticationProperties { RedirectUri = url }, "Cookies", "oidc", IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme, vm.ExternalAuthenticationScheme); – John Bowyer Dec 17 '19 at 22:13
  • The signout I was referring to is for the application, not for the identity provider. Only possible if logout is initiated from the application. Otherwise, you can't delete the application session cookie from your identity provider directly. Use one of the three global signout methods to get it. – Alpha75 Dec 19 '19 at 13:42
1

I built an MVC app with a separated API. I used IdentityServer4 for Auth and followed the steps above to add the Response.Cookies.Delete in the AccountController of IdentityServer4, worked fine. Anyway, my Client kept its cookies.

To remove them from the Client I added the same lines to the Logout Method before returning the SignOut.

    /// <summary>
    /// Handle logout page postback
    /// </summary>
    [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);

        if (User?.Identity.IsAuthenticated == true)
        {
            Response.Cookies.Delete(".AspNetCore.Identity.Application");
            Response.Cookies.Delete("idserv.external");
            Response.Cookies.Delete("idserv.session");

            // 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 { IsPersistent = true, RedirectUri = url }, vm.ExternalAuthenticationScheme);
        }

        return View("LoggedOut", vm);
    }
Michael Staples
  • 537
  • 7
  • 13