Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Timeout not working in ASP.Net MVC FormsAuthentication

I'm using FormsAuthentication, I'm having problems setting the TimeOut value.

I've seen some other posts related to this, but they don't seem to be exactly my problem or the solution suggested doesn't help.

My web.config has the following:

<authentication mode="Forms">
  <forms loginUrl="~/Account/LogOn"
         timeout="1"
         cookieless="UseCookies" />
</authentication>

I have put an AuthorizeAttribute on the controllers that I want to secure.

I can view the .ASPXAUTH cookie (using FireCookies) and I can see that it is set to expire in 1 minute after a login.

If I debug through my code I can see that FormsAuthentication.Timeout = 1.

However my ticket doesn't seem to timeout in 1 minute. After 1 minute of inactivity I can still browse to controllers with AuthorizeAttribute.

In fact I can actually delete the .ASPXAUTH cookie using FireCookies and I can still browse to controllers with an AuthorizeAttribute.

Bizarrely after being inactive for a long time (sorry don't have an exact time - I was out for lunch!) the TimeOut occurs and I am redirected to the login screen.

Any ideas?

like image 475
bplus Avatar asked Jan 24 '12 15:01

bplus


1 Answers

I too had the same problem. Actually, it came about because I could not read the forms authentication cookie from javascript, it was after a while undefined. I just wanted to know if I was authenticated via javascript.

Later I found that the ticket had expired, but I was not getting logged out (also. so i wanted to solve that too)! I saw your question had not been answered so I kept it open while I worked out my problems for half a day. The following is what I came up with that appears to be working.

My Answer is based on this answer. https://stackoverflow.com/a/454639/511438 by user ScottS

This is in my ASP.NET MVC 3 project.

Here is my login code. Not shown, the custom user authentication logic before it. This just sets the initial ticket.

public class FormsAuthenticationService : IFormsAuthentication

public void SignIn(string userName, bool createPersistentCookie, string role)
{
    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
            1,                             // version
            userName,           // user name
            DateTime.Now,                  // created
            DateTime.Now.Add(FormsAuthentication.Timeout),   // expires
            false,                    // rememberMe?
            role                        // can be used to store roles
            );

    string encryptedTicket = FormsAuthentication.Encrypt(authTicket);

    HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
    HttpContext.Current.Response.Cookies.Add(authCookie);
}

in the same class but a static method that is accessed from global.asax

//-- this is based on https://stackoverflow.com/questions/454616/asp-net-cookies-authentication-and-session-timeouts
internal static FormsAuthenticationTicket RefreshLoginCookie(bool retainCurrentExpiry)
{
    HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie == null || authCookie.Value == null)
        return null;

    FormsAuthenticationTicket oldTicket = FormsAuthentication.Decrypt(authCookie.Value);

    DateTime expiryDate = (retainCurrentExpiry ? oldTicket.Expiration : DateTime.Now.Add(FormsAuthentication.Timeout));
    HttpContext.Current.Response.Cookies.Remove(FormsAuthentication.FormsCookieName);

    var newTicket = new FormsAuthenticationTicket(oldTicket.Version, oldTicket.Name, oldTicket.IssueDate, expiryDate,
        oldTicket.IsPersistent, oldTicket.UserData, oldTicket.CookiePath);

    HttpCookie newAuthCookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(newTicket));
    HttpContext.Current.Response.Cookies.Add(newAuthCookie);

    return newTicket;

}

Global.asax

My customization comes that ajax requests do not refresh the forms authentication ticket. So if you sit there for the timeout period, an ajax request will log you out. Change that if you want ajax requests to keep the ticket alive (addresses my javascript cookie issue, not your logout inactivity issue). *(tip, if you get logged out, then login, but come back to the login page again, the first login did not specify a returnUrl in the querystring perhaps). *

protected virtual void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie == null || authCookie.Value == "")
    {
        return;
    }

    bool isAjax = new HttpRequestWrapper(System.Web.HttpContext.Current.Request).IsAjaxRequest();

    FormsAuthenticationTicket authTicket;
    try
    {
        //-- THIS IS WHAT YOU WANT
        authTicket = FormsAuthenticationService.RefreshLoginCookie(isAjax);
    }
    catch
    {
        return;
    }

    string[] roles = authTicket.UserData.Split(';');
    if (Context.User != null) Context.User = new GenericPrincipal(Context.User.Identity, roles);

}

Web.config here is the part where i set session timeout and ticket timeout

<configuration>
    <system.web>
        <sessionState mode="InProc" timeout="60" />
        <authentication mode="Forms">
            <forms loginUrl="~/Account/Login" timeout="60" name="ProviderMvcSession" cookieless="UseCookies" />
        </authentication>
like image 188
Valamas Avatar answered Oct 10 '22 15:10

Valamas