12

I have got a standard AccountController class of ASP.NET MVC5 project. When I try to log out user I am facing an error coz HttpContext is null. (I mean here HttpContext.GetOwinContext().Authentication is null)

So I cannot get how we can logout user when session ends...

In global.asax I have got this

protected void Session_Start(object sender, EventArgs e)
{
     Session.Timeout = 3; 
}

protected void Session_End(object sender, EventArgs e)
{
            try
            {
                 var accountController = new AccountController();
                 accountController.SignOut();
            }
            catch (Exception)
            {
            }
}

AccountController

public void SignOut()
{
      // Even if I do It does not help coz HttpContext is NULL
      _authnManager = HttpContext.GetOwinContext().Authentication;    

    AuthenticationManager.SignOut();


}

private IAuthenticationManager _authnManager;  // Add this private variable


public IAuthenticationManager AuthenticationManager // Modified this from private to public and add the setter
{
            get
            {
                if (_authnManager == null)
                    _authnManager = HttpContext.GetOwinContext().Authentication;
                return _authnManager;
            }
            set { _authnManager = value; }
}

Startup.Auth.cs has

 public void ConfigureAuth(IAppBuilder app)
        {
            // Enable the application to use a cookie to store information for the signed in user
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                ExpireTimeSpan = TimeSpan.FromMinutes(3),
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login")
            });
}
NoWar
  • 36,338
  • 80
  • 323
  • 498

6 Answers6

14

Assuming that you are using ApplicationCookie to store your login information.

AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
radbyx
  • 9,352
  • 21
  • 84
  • 127
  • 1
    It says the AuthManager does not have a method `SignOut` – Phil Apr 20 '17 at 13:50
  • 1
    You can try with var ctx = Request.GetOwinContext(); var authenticationManager = ctx.Authentication; authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie); – radbyx May 05 '17 at 06:08
  • @phil it just delete the cookie. Page doest not redirect to login page unless refresh is there any way to invalidate identity after signout on same request? – user6395764 Apr 18 '18 at 19:00
  • @msz Yes, I figured that out last year, haha – Phil Apr 18 '18 at 22:11
9

A call to Session_End() is causing the exception. That is totally expected since you cannot simply create new AccountController(), call accountController.SignOut() and expect it to work. This new controller is not wired up into the MVC pipeline - it does not have HttpContext and all its other requirements to be able to work.

You should log users out in response to a request that they have made. Create a new MVC project with Individual Accounts authentication. Open AccountController and take a look at the LogOff() method:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOff()
    {
        AuthenticationManager.SignOut();
        return RedirectToAction("Index", "Home");
    }

Here AuthenticationManager.SignOut() will be executed in response to a POST request at /Account/LogOff. Whenever such request arrives the ASP.NET/MVC will create an instance of AccountController and initialize it properly. After that the LogOff method will be called where you can actually execute AuthenticationManager.SignOut();.

Also in the default ASP.NET/MVC Application with Identity declares AuthenticationManager in the Helpers region of the code as follows:

private IAuthenticationManager AuthenticationManager { get { return HttpContext.GetOwinContext().Authentication; } }

Hope this helps.

Termato
  • 1,556
  • 1
  • 16
  • 33
Milan Nankov
  • 1,442
  • 12
  • 15
  • Yes, I agree. We have that method by default but I would like to force log out a user and redirect him to Login page. So I need solution to do it with OWIN. Anyway thank you for your opinion! – NoWar Oct 03 '14 at 17:05
  • @ClarkKent That solution does do it with OWIN, I have edited the answer to explain how it does that. Please see the pending edits. Milan explains why it throws an error before you get to log off your users. – Termato Oct 03 '14 at 17:06
  • Well... Ijust commented code within `Session_End` and I am facing strange behavior of the application. I put SessionTimeout 1 min. When I login and do nothing it is working fine. So 1 min later when I refresh pages it logs off and redirect to LOGIN page. But if during 2-3 mins. I am navigating within website it is not working. :) – NoWar Oct 03 '14 at 17:24
  • @ClarkKent Are you actively navigating through the website during those 2-3 mins? Have you tried going to a different page, sitting for a minute and then moving? If so, try and output your session variable to see if it is still set or getting reset. That or your function that logs the user out is not being called when you navigate to a different page. – Termato Oct 03 '14 at 17:28
  • Yeah. I use different pages to navigate. So when user is active somehow application (ASP.NET MVC) ignores 1 min extirpation interval... – NoWar Oct 03 '14 at 17:30
  • Well. I can confirm that configuration works like if user is inactive during 1 min it will force to log off user and if not then user can work and expiration interval does not have its impact. – NoWar Oct 03 '14 at 17:38
  • At least the logic behind the log out part works. I think if you figure out how to make that call to the other parts of the program, it will work. Have you tried setting the timeout in your **Web.Config**? ` ` **OR** ` ` – Termato Oct 03 '14 at 17:50
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/62432/discussion-between-termato-and-clark-kent). – Termato Oct 03 '14 at 17:52
  • 3
    Your code is a bit of a jumble but even if you get the calls to populate the context you may still face a separate issue as outlined in some bug requests on the codeplex site. https://katanaproject.codeplex.com/workitem/356 .You need to call AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie); not just AuthenticationManager.SignOut(); – rism Jan 22 '15 at 05:45
  • After using custom library to fix cookie problem with owin, this comment fixed my logout problems! Maybe now this tower will stand for a week... – Panu Oksala Mar 19 '15 at 15:37
3

I tried all this out:

System.Web.HttpContext.Current.GetOwinContext().Authentication.SignOut(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie);
FormsAuthentication.SignOut();
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);

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

Request.GetOwinContext().Authentication.SignOut(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie);

but finally this solved my problem:

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

Check

Community
  • 1
  • 1
nasir taha
  • 1,329
  • 1
  • 10
  • 7
2

For this you need to define a ActionFilter attribute and there you need to redirect the user to the respective controller action. There you need to check for the session value and if its null then you need to redirect the user. Here is the code below( Also you can visit my blog for detail step):

public class CheckSessionOutAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower().Trim();
            string actionName = filterContext.ActionDescriptor.ActionName.ToLower().Trim();

            if (!actionName.StartsWith("login") && !actionName.StartsWith("sessionlogoff"))
            {
                var session = HttpContext.Current.Session["SelectedSiteName"];
                HttpContext ctx = HttpContext.Current;
                //Redirects user to login screen if session has timed out
                if (session == null)
                {
                    base.OnActionExecuting(filterContext);


                    filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new
                    {
                        controller = "Account",
                        action = "SessionLogOff"
                    }));

                }
            }

        }

    }
}
Hrushikesh Patel
  • 266
  • 4
  • 12
2
Session.Abandon();
var owinContext = System.Web.HttpContext.Current.Request.GetOwinContext();
var authenticationTypes = owinContext.Authentication.GetAuthenticationTypes();
owinContext.Authentication.SignOut(authenticationTypes.Select(o => o.AuthenticationType).ToArray());

```

Stephan Ahlf
  • 3,310
  • 5
  • 39
  • 68
1

This worked for me

`public void SignOut()
    {
        IOwinContext context = _context.Request.GetOwinContext();
        IAuthenticationManager authenticationManager = context.Authentication;
        authenticationManager.SignOut(AuthenticationType);
    }
`

The only problem I have is there's no redirect to Login so I get a view not found error because the view I logged out from is under an [Authorize] attribute. I thought the automatic redirect was built in when a user is not authorized by this code block...

`app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = "ApplicationCookie",
        LoginPath = new PathString("/Account/Login"),
        ExpireTimeSpan = TimeSpan.FromHours(1),
    });
`
Daniel Jackson
  • 1,036
  • 1
  • 11
  • 35