Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are my forms authentication tickets expiring so fast?

I'm using forms authentication in an ASP.NET application. I configure the FormsAuthenticationTicket to expire in 1 year but it actually expires after 1 hour or so. I can't figure out why.

Here is all the code involved in the login process:

public static bool Login(int id)
{
    try
    {
        string securityToken = UserHelper.AuthenticateUser(id);

        DateTime expiryDate = DateTime.Now.AddYears(1);
        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
             1, id.ToString(), DateTime.Now, expiryDate, true,
             securityToken, FormsAuthentication.FormsCookiePath);

        string encryptedTicket = FormsAuthentication.Encrypt(ticket);
        HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
        cookie.Expires = expiryDate;

        HttpContext.Current.Response.Cookies.Add(cookie);

        return true;
    }
    catch
    {
        return false;
    }
}

Web.config:

<system.web>
    <machineKey validationKey="AutoGenerate"
    decryptionKey="AutoGenerate" validation="SHA1" />
    <compilation debug="true">
    <authentication mode="Forms">
        <forms loginUrl="~/Login.aspx" timeout="2880"/>
    </authentication>
...

Is something wrong with my approach? Why is it expiring so fast?

EDIT

Global.asax code:

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    if (Request.PhysicalPath.EndsWith(".aspx") || Request.PhysicalPath.EndsWith(".axd") || Request.PhysicalPath.EndsWith(".ashx"))
        SecurityManager.SetPrincipal();
}

SetPrincipal Code:

public static void SetPrincipal()
{
    ILivrePrincipal principal = null;
    FormsIdentity identity;
    UrlParameters urlParameters = UrlParametersHelper.GetUrlParameters(HttpContext.Current.Request);

    if (HttpContext.Current.Request.IsAuthenticated)
    {
        identity = (FormsIdentity)HttpContext.Current.User.Identity;

        User userProfile;
        urlParameters.SecurityToken = (((FormsIdentity)identity).Ticket).UserData;
        try
        {
            userProfile = UserHelper.GetUser(urlParameters.SecurityToken);
            UserHelper.UpdateLastActiveOn(userProfile);
            principal = new AuthenticatedPrincipal(identity, userProfile);
        }
        catch
        {
            //TODO: Log an exception
            FormsAuthentication.SignOut();
            principal = new AnonymousPrincipal(new GuestIdentity(), UserHelper.GetUser(null));
        }
    }
    else
    {
        principal = new AnonymousPrincipal(new GuestIdentity(), UserHelper.GetUser(null));
    }

    HttpContext.Current.User = principal;
}
like image 849
André Pena Avatar asked Jul 03 '10 03:07

André Pena


3 Answers

This is your problem.

<machineKey validationKey="AutoGenerate" 
            decryptionKey="AutoGenerate" 
            validation="SHA1"/>

ASP will generate a new machine key every time the app pool recycles. Which could reasonably happen every hour.

The machine key is used to encrypt and decrypt your FormsAuthentication cookie. If it changes, the cookie on your browser is no longer any good. So the system will treat you as if you have never logged on.

Try generating a static key and adding it to the configuration file. Should look something like this:

<machineKey  
    validationKey="21F090935F6E49C2C797F69(snip)F1B72A7F0A281B"          
    decryptionKey="ABAA84D7EC4BB56D75D(snip)B8BF91CFCD64568A145BE59719F"
    validation="SHA1"
    decryption="AES"
/>

Generate yourself a key here.

like image 56
John Wu Avatar answered Nov 06 '22 06:11

John Wu


I don't see anything wrong with the code. What browser are you using, perhaps it doesn't recognize the expiration date of 1 year? I would look at the response headers with fiddler or some such tool and see what's actually being sent.

like image 1
matt-dot-net Avatar answered Nov 06 '22 07:11

matt-dot-net


This might help http://support.microsoft.com/kb/910439/

My guess is that the cookie is expiring before the ticket. The above article shows you ways to debug to see if that is indeed the case.

like image 1
shookdiesel Avatar answered Nov 06 '22 06:11

shookdiesel