14

My project is based on the MVC 5 project template from Visual Studio 2013 (individual user account option). I have been relying on the default Sign In and Sign Out method for my users. But I'm not sure what I did, at some point, users cannot sign out anymore, however they can sign in as another user.

This is the default Logoff method of Account Controller

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOff()
    {
        AuthenticationManager.SignOut();
        return RedirectToAction("Index", "Home");
    }
    private IAuthenticationManager AuthenticationManager
    {
        get
        {
            return HttpContext.GetOwinContext().Authentication;
        }
    }

This is the default _LoginPartial.cshtml View that shows user's username.

    @using Microsoft.AspNet.Identity
    @if (Request.IsAuthenticated)
    {
        using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
        {
            @Html.AntiForgeryToken()

            <ul class="nav navbar-nav navbar-right">
                <li>
                    @Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
                </li>
                <li><a    href="javascript:document.getElementById('logoutForm').submit()">Log off</a>            </li>
            </ul>
        }
    }
    else
    {
        <ul class="nav navbar-nav navbar-right">
            <li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>
            <li>@Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
        </ul>
    }

When user signs out, it directs user to the login page, but user's username is still shown which means that they have not signed out. And the url on the browser shows http://localhost/Account/Login?ReturnUrl=%2FAccount%2FLogOff

It is not taking the user back to Index page of Home. So my guess is that something happened at the statement AuthenticationManager.SignOut();. I'm confused because I haven't changed anything to the Account Controller.

Any lead would be greatly appreciated.

Ramesisiii
  • 207
  • 1
  • 3
  • 10

5 Answers5

11

I had the same problem. Check this Issue on CodePlex:

http://web.archive.org/web/20160403071605/https://aspnetidentity.codeplex.com/workitem/2347

Try replacing AuthenticationManager.SignOut() with AuthenticationManager.Signout(DefaultAuthenticationTypes.ApplicationCookie);

I hope that I help you. :-)

Johann
  • 4,107
  • 3
  • 40
  • 39
  • 3
    My problem actually didn't happen at `SignOut()`. It's because I added `[authorize(Role = "admin")]` above the controller I didn't realize. But I'm sure it will help many people whose problem actually occurred at `SignOut()` using Owin Authentication. – Ramesisiii Mar 26 '15 at 06:45
  • 1
    @ Ramesisiii "It's because I added [authorize(Role = "admin")]" thank you for mentioned that. I spent many hours didn't know what caused my logout() method unable to get invoked by some account that is not an admin. +1 for you. – CB4 Mar 13 '17 at 15:02
9

Simply add this line of code after SignOut():

 HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);

Also check this out: Page.User.Identity.IsAuthenticated still true after FormsAuthentication.SignOut()

Community
  • 1
  • 1
Ice2burn
  • 677
  • 1
  • 8
  • 19
  • It turns out my problem didn't come from AuthenticationManager.SignOut(), but I still tested out the above statement on my project and it didn't work (user is still logged in). I think this solution might be specifically for **Forms Authentication**, and my project is using **Owin Authentication**. – Ramesisiii Mar 19 '15 at 07:59
  • Oh, it's never strikes then. I was having a problem (_LoginPartial View was showing username) then I was trying to logoff from the same page in the same request. That's why it's necessary to clear User HttpContext. This is useful when you sign out the current user and wish to respond with the actual page without doing a redirect. – Ice2burn Mar 20 '15 at 15:09
  • I have tried countless solutions until I found this one. This is it. I'm fairly sure I was having problem because I was having a problem doing the following on a single page : login then logout then login again. the last login would alway throw a token auth error. I was returning a _PartialLogin instead of doing the "traditional" redirectToAction. Using MVC 5, single page application. – Alexandre Jan 16 '19 at 09:49
  • This helps in a scenario where I wished to remove the current logged user. `Logoff` method was throwing some exception but this method worked fine. – Jamshaid K. Mar 19 '19 at 22:16
3

I figured my problem was not at SignOut(). If you think your problem is at SignOut() (and using Owin Authentication) check out Sergio's link.

For my case is a stupid mistake! I forgot I added [Authorize(Role = "admins")] to the controller, because I only wanted the admins to use the register method that comes with the default template. And the result is that no one except the admins can log out!

This is what I had:

[Authorize(Roles = "admin")]
public class AccountController : Controller
{
    public ActionResult LogOff()
    {
    }
    public ActionResult Register()
    {
    }
}

What I did is I just move the register methods to a new controller, like below:

[Authorize]
public class AccountController : Controller
{
    public ActionResult LogOff()
    {
    }
}

and

[Authorize(Roles = "admin")]
public class AdminController : Controller
{
    public ActionResult Register()
    {
    }
}

Now everyone can log out and only admins can register users. (And the default AuthenticationManager.SignOut() works fine.)

Community
  • 1
  • 1
Ramesisiii
  • 207
  • 1
  • 3
  • 10
2

Replace

AuthenticationManager.Signout(); 

with

AuthenticationManager.Signout(DefaultAuthenticationTypes.ApplicationCookie); 

as per the issue in Sergio's answer

Stuart Dobson
  • 3,001
  • 4
  • 35
  • 37
  • hey, if that was what Sergio was pointing to, maybe you should add that into his answer now that the Codeplex link doesn't work any more. – TechSavvySam Feb 16 '18 at 23:45
0

I have faced with the same problem..

Below is a standard ASP.Net MVC logOff procedure presented by Microsoft and it works, except user after logoff and login you will get wrong, It happens because authentication token. And as soon as you will release that it simple to modify. But nobody says about that.

// POST: /Account/LogOff
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);

    return RedirectToAction("Index", "Home");
}

As you can see that the standard way of logoff in AccountController

That the html code, with my little hack -> id="logoffbtn"

 @using (Html.BeginForm("LogOff", "Account"))
 {
 @Html.AntiForgeryToken()
  <button class="btn btn-default btn-flat" id="logoffbtn" 
  type="submit">Logout</button>
 }

So solution to properly logoff using standard way is to add somewhere in your main java script file little hack:

$(document).ready(function()
{
    try
    {
        $('#logoffbtn').click(function ()
        {
            // alert('Sign new href executed.');
            console.log("Session token start");
            sessionStorage.removeItem('accessToken');
            console.log("Session token done");
        });
    } catch (e)
    {
        console.log("Session token err");
    }
});

So what will happen next..basically after pressing logoff button you will clear access Token and now logoff will start working normally.

Hope that helps.

P.S. I have tried really many ways and only this was a hack for me.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Jevgenij Kononov
  • 1,210
  • 16
  • 11