Alexander Christov
Alexander Christov

Reputation: 10045

HttpContext.Authentication.SignOutAsync does not delete auth cookie

According to ASP.NET Core documentation the method HttpContext.Authentication.SignOutAsync() must delete the authentication cookie as well.

Signing out

To sign out the current user, and delete their cookie (italics mine - A.C.) call the following inside your controller

await HttpContext.Authentication.SignOutAsync("MyCookieMiddlewareInstance");

But it does not! Everything else seems okay, esp. auth scheme, because user gets signed-in correctly and the cookie .AspNetCore. is created.

Any ideas why cookie remains after the user's sing-out?

Upvotes: 44

Views: 52560

Answers (12)

Kitan
Kitan

Reputation: 124

I had the same issue recently. In my case, the browser had created multiple cookies. One with a name like ".AspNetCore.Antiforgery" and another one with a custom name that I had set for my cookie in startup.cs.

What solved the error for me was the first part of JTvermose's answer with some changes. I added the code below to my logout method. Worked like a charm.

if (HttpContext.Request.Cookies.Count> 0) 
{
    var siteCookies = HttpContext.Request.Cookies
        .Where(c => c.Key.Contains(".AspNetCore.") 
            || c.Key.Contains("Microsoft.Authentication"));
    foreach (var cookie in siteCookies)
    {
        Response.Cookies.Delete(cookie.Key);
    }
}

await HttpContext.SignOutAsync(
    CookieAuthenticationDefaults.AuthenticationScheme);
HttpContext.Session.Clear();
return RedirectToPage("/Index");

Upvotes: 10

Joemy Joseph
Joemy Joseph

Reputation: 11

This one will do the job like a charm.

await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
HttpContext.Session.Clear();

Upvotes: 1

Alimur Razi Rana
Alimur Razi Rana

Reputation: 480

In my case, this line of code works -

await HttpContext.SignOutAsync("Identity.Application");

Upvotes: 2

Qort
Qort

Reputation: 1

If what you're looking for is a way to make this if(HttpContext.User.Identity.IsAuthenticated) to result to false then do you can do this: HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));

Upvotes: 0

codearmalik
codearmalik

Reputation: 25

I use the following code

await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            Response.Cookies.Delete("CookieName");         
            return RedirectToAction("login", "Account");

Upvotes: 0

McGuireV10
McGuireV10

Reputation: 9926

You didn't post enough code to tell, but I suspect after you call SignOutAsync you have some type of redirect (for example, RedirectToAction) which overwrites the redirect to the OIDC endsession URL that SignOutAsync tries to issue.

(The same explanation for the redirect overwrite problem is given here by Microsoft's HaoK.)

Edit: If my speculation above is correct, the solution is to send a redirect URL in an AuthenticationProperties object with the final SignOutAsync:

// in some controller/handler, notice the "bare" Task return value
public async Task LogoutAction()
{
    // SomeOtherPage is where we redirect to after signout
    await MyCustomSignOut("/SomeOtherPage");
}

// probably in some utility service
public async Task MyCustomSignOut(string redirectUri)
{
    // inject the HttpContextAccessor to get "context"
    await context.SignOutAsync("Cookies");
    var prop = new AuthenticationProperties()
    {
        RedirectUri = redirectUri
    };
    // after signout this will redirect to your provided target
    await context.SignOutAsync("oidc", prop);
}

Upvotes: 39

Jan R
Jan R

Reputation: 33

In my case McGuireV10's answer didn't work as await context.SignOutAsync("oidc", prop); did not redirect to my given redirectUri.

I solved it by adding HttpContext.Response.Redirect(redirectUri); after the SignOutAsync call.

Upvotes: 1

Bronek
Bronek

Reputation: 11235

Maybe your case was to use ASP NET Core Identity authentication stuff like in my case

so, instead of using HttpContext.Authentication.SignOutAsync() or HttpContext.SignOutAsync() you can try to use API from ASP NET Identity:

SignInManager.SignOutAsync()

API from HttpContext didn't clear cookies with names starting with ".AspNetCore."

(to use SignInManager you need to bring in SignInMbanager by asp net core's DI)

Upvotes: 2

Amir Astaneh
Amir Astaneh

Reputation: 2196

Solved the issue with this first line.

await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
// await _SignInManager.SignOutAsync();
// HttpContext.Response.Cookies.Delete(".AspNetCore.Cookies");

Upvotes: 3

JTvermose
JTvermose

Reputation: 342

I solved the problem with deleting my site cookies with the following snippet placed in my Logout() method in the controller. I found that multiple cookies would be created by my site.

// Delete the authentication cookie(s) we created when user signed in
            if (HttpContext.Request.Cookies[".MyCookie"] != null)
            {
                var siteCookies = HttpContext.Request.Cookies.Where(c => c.Key.StartsWith(".MyCookie"));
                foreach (var cookie in siteCookies)
                {
                    Response.Cookies.Delete(cookie.Key);
                }
            }

And in Startup.cs:

app.UseCookieAuthentication(new CookieAuthenticationOptions()
            {
                AuthenticationScheme = "Cookies",
                LoginPath = new PathString("/Account/Login/"),
                AccessDeniedPath = new PathString("/Home/Index/"),
                AutomaticAuthenticate = true,
                AutomaticChallenge = true,
                CookieName = ".MyCookie"
            });

Notice that I do not use await HttpContext.Authentication.SignOutAsync("MyCookieMiddlewareInstance"); since I am using OpenIdConnect with Google.

Upvotes: 2

Castro JR
Castro JR

Reputation: 41

I've got the same problem. SignOutAsync does not work as should .

I found this:

Response.Cookies.Delete(".AspNetCore.<nameofcookie>");

Upvotes: 4

Alexander Christov
Alexander Christov

Reputation: 10045

Here's the code that deletes the cookie (If nothing else helps, use brute force):

await this.HttpContext.Authentication.SignOutAsync(<AuthenticationScheme>);

// ...

var cookie = this.Request.Cookies[<CookieName>];
if (cookie != null)
{
    var options = new CookieOptions { Expires = DateTime.Now.AddDays(-1) };
    this.Response.Cookies.Append(cookieName, cookie, options);
}

Bad, bad, bad! Seems like a very ugly patch! But works... :(

Any other solutions?

Upvotes: 2

Related Questions