Search code examples
identityserver4

Can't get IdentityServer4 logout to work for external (Google) authentication


I am working through IdentityServer4 quickstart and trying to get the external (Google) authentication to work. I am able to login through Google but after that login, even if I click Logout, I always automatically get in in the following times.

Here is the logout logic from AccountController.cs

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

    return View("LoggedOut", vm);
}

My internal authentication login and logout works just fine by the way. Could someone tell me what I might be missing here?

Update-1

Further debugging shows that the value of vm.TriggerExternalSignout in Logout function is always false when logging out. The variable TriggerExternalSignout only appears twice in source code in the entire solution. The first one is in Logout above and the other is in LoggedOutViewModel.cs as shown below:

enter image description here

The immediate reason why TriggerExternalSignout is false is because the value of the property ExternalAuthenticationScheme is always null. The only place the ExternalAuthenticationScheme get set is in AccountController's BuildLoggedOutViewModelAsync function (see screenshot below), which never seems to be invoked (break point never get hit) during login and logout.

enter image description here

And that's because the value of providerSupportsSignout is false. This makes some sense since Google doesn't support signout, but what should I do to make my logout work?

Update-2

I added the logout logic, as nahidf suggested in his answer, in the BuildLoggedOutViewModelAsync function as the following:

enter image description here

Unfortunately, the logout still doesn't seem to work - I got to the page that says I am logged out after clicking logout from a Google login, but I still get right in by clicking on Google login button when I try to start a new session.

What am I doing wrong here?


Solution

    • Check if TriggerExternalSignout is true in your case, if not should investigate why is that
    • If TriggerExternalSignout is already true, try
       // delete local authentication cookie
      await HttpContext.SignOutAsync();
    
      // Clear the existing external cookie to ensure a clean login process
      wait HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme);
    
      // Clear the existing external cookie to ensure a clean login process
      await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
    

    When we logout from IdentityServer4, it just log user out from our application. It will NOT log the user out of their Google account. Google doesn't support third party logout.

    Edit: For google case TriggerExternalSignout is false as google doesnt support external logout. Ref in code