Question

I have an ASP.NET MVC 5 website with OWIN authentication. Each user has distinct credentials in the underlying database, which is also used to authenticate the user through a custom UserManager. I store the username/password in session state before UserManager.FindAsync returns, as the application will need to use them for database access in any subsequent request by the same user.

When the session is lost (AppDomain recycling for example), the credentials are lost with it. But Owin keeps authenticating the user, probably on the basis of the cookie sent by the browser. What I end up with is an authenticated user... with no session and therefore no database credentials.

The easiest way to reproduce this behavior is to create a new ASP.NET MVC 5 application with Individual User Accounts authentication, and add some session data at the the end of the AccountController.SignInAsync method.

private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);

    HttpContext.Session["Data"] = "Data";
}

Then, try to retrieve this information in any controller.

public ActionResult About()
{
    ViewBag.Message = Session["Data"];

    return View();
}

The data will be present after the user logged in. But if you keep the browser opened (for the cookie), restart the development server and refresh the page, the user is still authenticated while the data has disappeared.

I know this behavior is not unexpected, but I'm searching for a reliable and centralized way to force redirection to the login page when the session has expired or disappeared for any other reason.

Was it helpful?

Solution

Set the cookie expiration at the same duration as your session timeout value. In addition you will need to make sure that the type of expiration (sliding or non-sliding) are the same. Using non-sliding expiration will probably have better results in making sure they timeout at the same time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top