1

I have just created my first MVC Application using the Open Id Connect Protocol under Identity Server 4 and .Net Core 2.0. The application is performing as expected during the Login flow where the user is redirected to the Login form hosted in my Identity Server service.

Where I am currently having an issue is that after I go through the Logout flow the application "appears" to behave as expected and is showing the user as logged out/not authenticated.

However on the next access of a protected method in my Web App the middleware is automatically logging the user back in by making a request to Identity Server in the background without asking for a username or password.

I have used the Implicit MVC Client from the Identity Server Samples to rule out any of my client code but the same thing happens.

I was wondering if anyone has experienced this issue and how they managed to resolve it.

My Startup.cs in the client looks as below:

services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = "oidc";
        })
            .AddCookie(options =>
            {
                options.Cookie.Name = "mvcimplicit";
            })
            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority = Constants.Authority;
                options.RequireHttpsMetadata = false;

                options.ClientId = "lipaspotwebui";

                options.Scope.Clear();
                options.Scope.Add("openid");
                options.Scope.Add("profile");
                //options.Scope.Add("email");
                options.AuthenticationMethod = OpenIdConnectRedirectBehavior.FormPost;

                options.SaveTokens = true;

                options.TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = JwtClaimTypes.Name,
                    RoleClaimType = JwtClaimTypes.Role,
                };
            });

Here is the code from my Logout method in my client application:

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

It would appear from my investigations that the user details are being cached at the client somehow and being passed up in the call to the Identity Server but that is only an assumption tbh.

Any help on this would be much appreciated.

Stuart

Edit:

I have now confirmed that the issue is the .AspNet.Identity.Application cookie that is being created as part of the application login. The issue I have now is how to get rid of this as have tried the suggestions below to no avail. Is there any way to easily get rid of this on my CleanUp action?

Edit #2

As suggested I cleared out all my browser cookies before starting. Here are the cookies at each stage

After Initial Login

Cookies List after Login

After Logout (redirected from Identity Server 4)

Cookies List After Logout

After accessing a protected method in Client Site

Cookies List After Accessing Protected Method

It is important to note that as mentioned above that when I access the protected method after the logout has completed I am not prompted for my Username/Password again which IMO cant be desired method for this system to work.

Stuart Ferguson
  • 367
  • 3
  • 16
  • where is the SignoutResult() located? – rkmorgan Jan 04 '18 at 17:43
  • In the Authenticate controller of the MVC client application – Stuart Ferguson Jan 04 '18 at 17:46
  • sounds like the cookie is still alive after logout and the client has been setup with 'offline-access'. Have you ever read the following topic? https://stackoverflow.com/questions/28999318/owin-authentication-signout-doesnt-seem-to-remove-the-cookie it might be helpful. P.S. I do logout with the following comment and seems fine so far. Request.GetOwinContext().Authentication.SignOut(); – rkmorgan Jan 04 '18 at 17:54

2 Answers2

1

You should have this:

Request.GetOwinContext().Authentication.SignOut();

in your Logout method in the client. Then the LogoutUri of the client (registered in IDS), should point to a method, in your client (for example: https://clientUrl/Home/SignoutCleanup), which has the following in it:

public void SignoutCleanup(string sid)
    {
        var cp = (ClaimsPrincipal)User;
        var sidClaim = cp.FindFirst("sid");
        if (sidClaim != null && sidClaim.Value == sid)
        {
            Request.GetOwinContext().Authentication.SignOut("Cookies");
        }
    }

So far this things works like charm for us.

EDIT: For .NET Core clients, because there is no Request.GetOwinContext()

you should use:

Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.SignOutAsync(HttpContext);

You can see other answers, saying that you can also use:

HttpContext.Authentication.SignOutAsync("Cookies");

But it is already obsolete and will be removed.

m3n7alsnak3
  • 3,026
  • 1
  • 15
  • 24
  • Is this valid under core 2.0 ? – Stuart Ferguson Jan 04 '18 at 18:48
  • If you are asking about is it valid with IDS 4 which runs on core 2.0 - this is exactly our setup. – m3n7alsnak3 Jan 04 '18 at 19:04
  • In my ID4 client there isnt a LogoutUri property only Back and Front Channel Logout Uri, which one of these should be set? – Stuart Ferguson Jan 04 '18 at 20:24
  • @StuartFerguson - sorry, my mistake. Depending on your client - check here http://docs.identityserver.io/en/release/topics/signout.html – m3n7alsnak3 Jan 04 '18 at 20:41
  • @m3n7alsnak3 as per your answer, I tried to use `BackChannelLogout` protocol. When I hit logout in client (I also set and pass `id_token` with logout request and in IDS 4 logout id come as expected.) it triggers `SignoutCleanup` function. But, `sid` always `null`. – Balagurunathan Marimuthu May 13 '20 at 11:47
0

As mentioned by m3n7alsnak3, HttpContext.Authentication.SignOutAsync is obsolete but it was replaced with HttpContext.SignOutAsync -- and you need to call it for OIDC as well. Try this:

await HttpContext.SignOutAsync("mvcimplicit");
await HttpContext.SignOutAsync("oidc");
Zoe
  • 27,060
  • 21
  • 118
  • 148
McGuireV10
  • 9,572
  • 5
  • 48
  • 64
  • This is in my Logout controller method in my MVC client application? – Stuart Ferguson Jan 04 '18 at 20:23
  • @StuartFerguson - Yes, and can you also clarify which framework is your Client using. .NET or .NET Core, because depending on the framework, the answer is different - check my answer. – m3n7alsnak3 Jan 04 '18 at 20:43
  • Client is .net core 2.0 also – Stuart Ferguson Jan 04 '18 at 20:51
  • @StuartFerguson - As I said - check the Edit of my answer. In your case you need to use Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.SignOutAsync(HttpContext); in your client logout method – m3n7alsnak3 Jan 04 '18 at 21:22
  • @m3n7alsnak3 Will this alone trigger the redirect to the Logout page within the ID4 server ? – Stuart Ferguson Jan 04 '18 at 22:10
  • Yes it will, and then IDS will redirect to your client's postlogoutredirecturi – m3n7alsnak3 Jan 04 '18 at 23:24
  • @m3n7alsnak3 Ok thanks, I will give that a try, do i still need to use one of the Logout Uri (Back or Front Channel) properties to do local clean up at the client like you suggested below? and if yes do these need to be set to the whole uri of the client clean up action? – Stuart Ferguson Jan 05 '18 at 08:08
  • Those two lines are the only things a Core client needs to log out. You need _both_ sign-outs... there are two cookies to clear. The OIDC `Authority` in the client Setup class is enough to make it work, the `SignOffAsync` method uses the OIDC "discovery" info to figure out the complete logoff address. The only other thing you probably need is to set `PostLogoutRedirectUris` on the IdentityServer side so that IdentityServer knows where to send the user after logoff is complete. – McGuireV10 Jan 05 '18 at 12:25
  • Also I highly recommend manually clearing your cookies on each test-run until you get it right. When I was learning this I had situations where the code was finally fixed but previous errors had left me in a state where nothing worked right until I started from a clean slate. Might save you some headaches! – McGuireV10 Jan 05 '18 at 12:33
  • So you saying @McGuireV10 there is no need for the SignOutCleanUp method as suggested below that is called by the Identity Server as configured in the Front/back Channel Logout Uri? – Stuart Ferguson Jan 05 '18 at 14:53
  • Correct -- no need for it as far as IdentityServer is concerned. You may have some business case for wiping the claims and reloading them, but they aren't the cause of the problem you're asking about. – McGuireV10 Jan 05 '18 at 18:45
  • @McGuireV10 i have added some screenshots of the cookies list at each stage could you review these and tell me if this is what you expect, thanks. – Stuart Ferguson Jan 05 '18 at 20:09
  • Ah, sorry, I don't use ASP.NET Identity. The way it handles claims is kind of screwy, and I also dislike ORMs, especially Entity Framework. But I can tell you just the two sign-out methods I listed do work with persistence on the IdentityServer4 side. (I have a GitHub repo of IdentityServer4 + QuickStart demonstrating persistence with ADO.NET [here](https://github.com/MV10/IdentityServer4.AdoPersistence).) – McGuireV10 Jan 06 '18 at 13:12