asp.net-mvcasp.net-coreidentityserver4asp.net-authentication

Identity Server 4 Post Logout URL Null


I'm having some issues trying to figure out how to get the post logout URL working in my ASP.NET Core MVC application. I have been following examples from the Identity Server documentation and other posts, though I'm not quite sure where I'm going wrong. The user is successfully logged out of the application, then redirected to Identity Server and logged out there, but I notice that the id_token parameter is not being passed to Identity Server, so even though the post logout parameter is present, it's not being used.

My middleware config looks correct, I feel it's an issue with how I'm creating the application cookie and the token is not really being saved anywhere where it can be re-used.

I'm currently only using the "code" response type, but this does seem to also include an identity token along with the authorization token.

Startup.cs:

services.AddAuthentication(options =>
            {
                options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = "oidc";
            })
            .AddJwtBearer("Bearer", options =>
            {
                options.Authority = Configuration["IdentityServerSettings:AuthorityUrl"];
                options.RequireHttpsMetadata = false;
                options.Audience = Configuration["IdentityServerSettings:Audience"];
            })
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority = Configuration["IdentityServerSettings:AuthorityUrl"];
                options.ClientId = "myClient";
                options.RequireHttpsMetadata = false;
                options.SaveTokens = true;
                options.SignedOutRedirectUri = "http://localhost:55690/account/logoutcallback";
                options.SignedOutCallbackPath = "/account/logoutcallback";
                options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            });

AccountController.cs

Logout methods:

public async Task<IActionResult> Logout()
    {
        return new SignOutResult(new[] { CookieAuthenticationDefaults.AuthenticationScheme, "oidc" });
    }

    public async Task<IActionResult> LogoutCallback()
    {
        return RedirectToAction(nameof(Dashboard), "Account");
    }

Login callback:

if (!Request.Query.ContainsKey("code"))
                throw new Exception($"Request query string does not contain an authorization code. Query string: {Request.QueryString.Value}");

            var authCode = Request.Query["code"].ToString();

            TokenResponse tokenResponse = null;
            using (var httpClient = new HttpClient())
            {
                tokenResponse = await httpClient.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest
                {
                    Address = _configuration["IdentityServerDashboardSettings:TokenUrl"],
                    ClientId = _configuration["IdentityServerDashboardSettings:ClientId"],
                    RedirectUri = _configuration["IdentityServerDashboardSettings:RedirectUrl"],
                    Code = authCode
                });
            }

            var handler = new JwtSecurityTokenHandler();
            var jwtToken = handler.ReadToken(tokenResponse.AccessToken) as JwtSecurityToken;

            var identity = new ClaimsIdentity(jwtToken.Claims, CookieAuthenticationDefaults.AuthenticationScheme);
            identity.AddClaim(new Claim("id_token", tokenResponse.IdentityToken));

            var claimsPrinciple = new ClaimsPrincipal();
            claimsPrinciple.AddIdentity(identity);

            await HttpContext.SignInAsync(claimsPrinciple);

            return RedirectToAction(nameof(Dashboard), "Account");

Everything else works fine, SignOutResult successfully constructs the logout URL and redirects to Identity Server, but it's missing the id_token in the parameters. I can't really find any examples on how I'm supposed to store this for later use, a lot of examples I've came across seem to just work automatically. Is there something I've configured wrong?


Solution

  • To redirect back to MVC client, make following changes:

    1. Change PostLogoutRedirectUris on Client's config within IdentityServer to be like this:
    PostLogoutRedirectUris = { "http://localhost:55690/signout-callback-oidc"
    
    
    1. On MVC client's OpenId connect setup remove SignedOutRedirectUri and SignedOutCallbackPath

    The default value for AccountOptions - AutomaticRedirectAfterSignOut is false and you may see a page like image bellow, asking to click on here to get back to mvc client:

    enter image description here

    for automatic redirect you can set AccountOptions - AutomaticRedirectAfterSignOut to true on IdentityServer project.

    Here is a sample I did myself.