FormsAuthenticationTicket.Expiration value changing

Last post 04-07-2008 5:53 PM by sschack. 17 replies.

Sort Posts:

  • FormsAuthenticationTicket.Expiration value changing

    10-28-2006, 11:46 PM
    • Member
      126 point Member
    • MikeOtown
    • Member since 01-05-2005, 10:12 AM
    • Posts 40

    I am creating a FormsAuthenticationTicket and specifying the timout to be different than the value in web.config.  It works fine until the user gets to another page and somehow the FormsAuthenticationTicket.Expiration in the cookie is changed to reflect the timeout in the web.config.

     Here is the code in Login.asp.cs:

    FormsAuthenticationTicket authTicket = new

    FormsAuthenticationTicket(Login1.UserName,

    Login1.RememberMeSet, iMinutes); // set Expiration

     

    string encryptedTicket = FormsAuthentication.Encrypt(authTicket);

    HttpCookie authCookie = new HttpCookie(

    FormsAuthentication.FormsCookieName, encryptedTicket);

    authCookie.Expires = authTicket.Expiration;

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

    e.Authenticated = true; // authTicket.Expiration is correct here

    And here is the code in the following page Load event:

    FormsAuthenticationTicket fat = FormsAuthentication.Decrypt(Request.Cookies[".ASPXAUTH"].Value);

    Response.Write("fat.expires=" + fat.Expiration); // expiration ends up as 30 minutes from login here

  • Re: FormsAuthenticationTicket.Expiration value changing

    10-29-2006, 1:42 AM
    Answer
    • All-Star
      17,710 point All-Star
    • vivek_iit
    • Member since 06-18-2006, 6:13 PM
    • New Delhi
    • Posts 3,171
    • TrustedFriends-MVPs

    Hi,

    I blogged about this strange behavior in ASP.NET 2.0 recently:

    http://geekswithblogs.net/vivek/archive/2006/10/13/93956.aspx

    I think the functionality has changed and has "crippled" ASP.NET.

    Let me know what you think.

    Vivek

  • Re: FormsAuthenticationTicket.Expiration value changing

    10-29-2006, 8:42 AM
    • Member
      126 point Member
    • MikeOtown
    • Member since 01-05-2005, 10:12 AM
    • Posts 40
    Yes, it looks like the ability to set the timeout value of a FormsAuthenticationTicket in ASP .NET 2.0 is broken.  I haven't seen any other posts about this besides yours.  Microsoft - please acknowledge this issue!!  I wasted hours trying to get this to work.  Releasing a fix would be nice also.
  • Re: FormsAuthenticationTicket.Expiration value changing

    10-30-2006, 4:03 PM
    • Contributor
      3,067 point Contributor
    • sschack
    • Member since 09-16-2003, 12:06 PM
    • Posts 613
    • AspNetTeam
      Moderator

    From the post I'm not sure if the sample code is being used inside of the Login control or not.  I did try the following code in just a plain .aspx page used for login:

                //Manual cookie issuance
                FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(txtUserId.Text, false, 200); //hardcoded 200 minute duration
                string encryptedTicket = FormsAuthentication.Encrypt(authTicket);

                HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
                HttpContext.Current.Response.Cookies.Add(authCookie);
                Response.Redirect("default.aspx"); 

     And then in default.aspx writing out the expiration time:

            FormsAuthenticationTicket fat = FormsAuthentication.Decrypt(Request.Cookies[".ASPXAUTH"].Value);
            Response.Write("fat.expires=" + fat.Expiration);

     This is returning the correct expiration as set on the login page.

    However, if you are attempting to set the cookie from inside of the Login control's Authenticate event, this event is too early to be setting the cookie manually.  The login control event sequence looks like:

            Raises the Authenticate event --->  Login control sets the cookie with a call to SetAuthCookie -->  Raises the LoggedIn event

    To manually control the cookie expiration and cookie issuance, put the cookie code in the LoggedIn event.  I would recommend first removing the cookie set by the Login control (HttpContext.Current.Response.Cookies.Remove), and then re-issuing the cookie manually.

    One other quick note:  you should only set the cookie's expiration property if the user indicated they wanted a persistent cookie.  The code shown in the post is always setting the HttpCookie's expiration date, which has the effect of always making the cookie persistent.

    -Stefan
    ----------------------------------------------------------
    This posting is provided "AS IS" with no warranties, and confers no rights.
  • Re: FormsAuthenticationTicket.Expiration value changing

    10-30-2006, 4:03 PM
    • Contributor
      3,067 point Contributor
    • sschack
    • Member since 09-16-2003, 12:06 PM
    • Posts 613
    • AspNetTeam
      Moderator

    From the post I'm not sure if the sample code is being used inside of the Login control or not.  I did try the following code in just a plain .aspx page used for login:

                //Manual cookie issuance
                FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(txtUserId.Text, false, 200); //hardcoded 200 minute duration
                string encryptedTicket = FormsAuthentication.Encrypt(authTicket);

                HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
                HttpContext.Current.Response.Cookies.Add(authCookie);
                Response.Redirect("default.aspx"); 

     And then in default.aspx writing out the expiration time:

            FormsAuthenticationTicket fat = FormsAuthentication.Decrypt(Request.Cookies[".ASPXAUTH"].Value);
            Response.Write("fat.expires=" + fat.Expiration);

     This is returning the correct expiration as set on the login page.

    However, if you are attempting to set the cookie from inside of the Login control's Authenticate event, this event is too early to be setting the cookie manually.  The login control event sequence looks like:

            Raises the Authenticate event --->  Login control sets the cookie with a call to SetAuthCookie -->  Raises the LoggedIn event

    To manually control the cookie expiration and cookie issuance, put the cookie code in the LoggedIn event.  I would recommend first removing the cookie set by the Login control (HttpContext.Current.Response.Cookies.Remove), and then re-issuing the cookie manually.

    One other quick note:  you should only set the cookie's expiration property if the user indicated they wanted a persistent cookie.  The code shown in the post is always setting the HttpCookie's expiration date, which has the effect of always making the cookie persistent.

    -Stefan
    ----------------------------------------------------------
    This posting is provided "AS IS" with no warranties, and confers no rights.
  • Re: FormsAuthenticationTicket.Expiration value changing

    10-30-2006, 4:54 PM
    • Member
      126 point Member
    • MikeOtown
    • Member since 01-05-2005, 10:12 AM
    • Posts 40

    Thanks.  I'll try that.

     I thought that you could implement your own authentication by implementing the Login control's Authenticate event.  I guess issuing the cookie isn't considered part of authentication.

    I am setting e.Authenticated = true in the Authenticate event.

    So there is no way to tell the Login control to NOT issue a cookie?

  • Re: FormsAuthenticationTicket.Expiration value changing

    10-30-2006, 5:16 PM
    • Contributor
      3,067 point Contributor
    • sschack
    • Member since 09-16-2003, 12:06 PM
    • Posts 613
    • AspNetTeam
      Moderator
    Yes - but with the workaround noted earlier:  remove the cookie in the LoggedIn event of the Login control.  I think the control designers felt that with the number of events already on the control, they didn't want to add another one that specifically dealt with issuing the cookie.
    -Stefan
    ----------------------------------------------------------
    This posting is provided "AS IS" with no warranties, and confers no rights.
  • Re: FormsAuthenticationTicket.Expiration value changing

    10-31-2006, 12:35 PM
    • All-Star
      17,710 point All-Star
    • vivek_iit
    • Member since 06-18-2006, 6:13 PM
    • New Delhi
    • Posts 3,171
    • TrustedFriends-MVPs

    Stefan,

    I think I am doing something really stupid because your code above doenst seem to be working as expected (and I am not using Login control). Here is my code in the Login page:

    public partial class Login : System.Web.UI.Page

    {

    protected void Page_Load(object sender, EventArgs e)

    {

    string Username = "vivekT";

    if (TextBox1.Text == "a")

    {

    //HttpCookie cookie = FormsAuthentication.GetAuthCookie(Username, true); //true is used to create a persistent cookie

    // cookie.Expires = DateTime.Now.AddMonths(3); //DOESNT WORK in 2.0 as value is taken from "timeout" attribute in the config file

    //Manual cookie issuance

    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(Username, true, 200); //hardcoded 200 minute duration

    string encryptedTicket = FormsAuthentication.Encrypt(authTicket);

    HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);

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

    Response.Redirect("default.aspx");

     

    //Response.Cookies.Add(cookie);

    //Response.Redirect(FormsAuthentication.GetRedirectUrl(Username, true));//redirect to the originally requested page

    }

    }

    }//end class

    Note that if I remove the  commented code, and set the web.config timeout value to a large number, then it seems to work (till the timeout value specified).

    Please let me know what I am missing here!

    Thanks,

    Vivek

  • Re: FormsAuthenticationTicket.Expiration value changing

    10-31-2006, 3:41 PM
    • Member
      126 point Member
    • MikeOtown
    • Member since 01-05-2005, 10:12 AM
    • Posts 40

    You are not setting the Expiration property of the cookie.

  • Re: FormsAuthenticationTicket.Expiration value changing

    10-31-2006, 4:13 PM
    • Contributor
      3,067 point Contributor
    • sschack
    • Member since 09-16-2003, 12:06 PM
    • Posts 613
    • AspNetTeam
      Moderator

    I think there is a bit of confusion over the expiration of the forms authentiction ticket, versus the concept of expiration on the cookie itself.  The forms authentication feature only looks at the expiration time set on the forms authentication ticket. It never looks at the expiration date set on the cookie itself.  The reason is that the forms authentication ticket is encrypted and digitally signed, so its payload can be trusted.  However a malicious user can easily forge an Http cookie with a fake expiration date.  The only purpose of the cookie's expiration date in forms authentication is that by explicitly setting an expiry date, the cookie will be persisted in the user's browser cache.  This how "remember me" functionality works - the forms auth ticket is packaged into a cookie and the cookie has an explicit expiration date.  That way when a user returns to the site at some future point in time, the browser just automatically sends the forms auth cookie back to the server.  However the server decrypts the payload of the cookie, and then looks at the expiration date contained in the payload (not the expiry date of the cookie itself) to determine if the forms auth ticket should still be considered valid.

    Unless the intent is to make the cookie stick around on a user's machine, you don't need to set the Expiration property of the HttpCookie.  If you do want a persistent cookie, then when you manually issue it you need to ensure that the expiration date in the forms auth ticket and the expiry on the coookie itself are using the same duration.  Otherwise you can end up in a weird situation where the date in the forms auth ticket and the date on the cookie don't match.

    -Stefan
    ----------------------------------------------------------
    This posting is provided "AS IS" with no warranties, and confers no rights.
  • Re: FormsAuthenticationTicket.Expiration value changing

    11-01-2006, 12:19 AM
    • All-Star
      17,710 point All-Star
    • vivek_iit
    • Member since 06-18-2006, 6:13 PM
    • New Delhi
    • Posts 3,171
    • TrustedFriends-MVPs

    > If you do want a persistent cookie, then when you manually issue it you need to ensure that the expiration date in the forms auth ticket and the expiry on the coookie itself are using the same duration.

    Thanks for the clarification! But am I right when I say that the behavior has changed in 2.0 because in 1.1 we never used toset FormsAuthenticationTicket explicitly to create persistent cookies. We just used to create a manual cookie, set its expiration time and leave the rest to ASP.NET.

    Also, still there are many ASP.NET 2.0 books out there (some of them quite famous) where it is mentioned that to create persistent cookies, one just needs to create a manual cookie and set its expiration time. No mention of setting FormsAuthenticationTicket's expiration at all!

    Let me know your thoughts on this.

    Vivek

  • Re: FormsAuthenticationTicket.Expiration value changing

    11-01-2006, 2:17 PM
    • Contributor
      3,067 point Contributor
    • sschack
    • Member since 09-16-2003, 12:06 PM
    • Posts 613
    • AspNetTeam
      Moderator

    In ASP.NET 2.0 you also don't need to explicitly create a ticket to create a persistent forms auth cookie.  However what changed between the two releases is that in ASP.NET 2.0 persistent cookies now use the expiration time defined in the forms authentication configuration section.  In ASP.NET 1.0/1.1 persistent forms auth cookies always defaulted to a 50 year expiration.  Because of this difference in behavior developers frequently find they need to manually issue persistent forms auth tickets because they need to use a longer expiration time than what is set in config (by default config is set to 30 minutes I believe).

    Regarding the guidance about setting only the cookie expiration - developers definitely need to make sure the expiration time used when creating a FormsAuthenticationTicket has the correct time in it.  The expiry date on the HttpCookie itself just governs how long the cookie sits in a user's browser cache.  ASP.NET though never trusts that value, and always uses the expiration time from inside of the ticket as the indicator of whether or not the ticket is still considered valid.

    -Stefan
    ----------------------------------------------------------
    This posting is provided "AS IS" with no warranties, and confers no rights.
  • Re: FormsAuthenticationTicket.Expiration value changing

    11-01-2006, 2:33 PM
    • All-Star
      17,710 point All-Star
    • vivek_iit
    • Member since 06-18-2006, 6:13 PM
    • New Delhi
    • Posts 3,171
    • TrustedFriends-MVPs

    Stefan,

    Thanks a lot for the detailed explaination. Is there any specific reason why this behavior changed? I can only think that using web.config's default value instead of 50 years default will make persistent cookies "more secure".

    Thanks,

    Vivek

  • Re: FormsAuthenticationTicket.Expiration value changing

    11-12-2007, 1:25 PM
    • Member
      14 point Member
    • bustell
    • Member since 07-11-2003, 7:36 AM
    • Rochester, NY
    • Posts 18

     OK, I've just spent 2 hours of my life trying to figure out how FormsAuthentication.RedirectFromLoginPage works and I am more confused than when I started.  I've read all kinds of complicated answers to session time-outs and persistent cookie time-out (which I find interesting... persistent should be persistent).

    I am trying to use the Microsoft Login control, but have custom code behind the authenticate event.

    The code basically says if the user's password is good (look up in dateabase), then perform FormsAuthentication.RedirectFromLoginPage(Me.Login1.UserName, Me.Login1.RememberMeSet)

    Unfortunately, if the user click Remember Me, it does really remember them.  Very frustrating.  I have searched the Internet and can't come up with an answer / explanation that I understand.  Maybe, I'm just being stupid today.  I'm not sure.

    In one forum, it was mentioned that you can not use RedirectFromLoginPage within the authenticate event because it was too early to set the cookie and that had to be done in the LoggedIn event.  So I added e.authenticated = True to my authenticate event and then added the FormsAuthentication.RedirectFromLoginPage(Me.Login1.UserName, Me.Login1.RememberMeSet) to the LoggedIn event.  Still not working.

    Does anyone have an example of how to use the login control with your own custom authenticate event?  I'm not using Microsoft's Membership at all.  I have my own user/roles/resources tables that I authenticate with.
     

  • Re: FormsAuthenticationTicket.Expiration value changing

    04-05-2008, 7:35 AM
    • All-Star
      45,563 point All-Star
    • haidar_bilal
    • Member since 07-14-2003, 1:43 AM
    • Lebanon - Beirut
    • Posts 8,726

    Hi Stefan,

    I am noticing a strange behavior in ASP.NET 3.5.

    I have added the following into the page_load of the Login.aspx page:

    FormsAuthentication.RedirectFromLoginPage("testuser", true);

     

    Inside the page_load of the Default.aspx page, I add the following: 

            // Retrieve the FormsAuthentication Cookie
            HttpCookie cookie = (HttpCookie)Request.Cookies[FormsAuthentication.FormsCookieName];
            
            // Get the cookie's payload == Enrypted FormsAuthenticationTicket 
            string encryptedTicket = cookie.Value;
    
            // Decrypt the cookie's payload 
            FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(encryptedTicket);
    
            Response.Write("Ticket Expiry Date: " + ticket.Expiration.ToLocalTime().ToLongDateString() + ticket.Expiration.ToLocalTime().ToLongTimeString() +" <br/>");
            Response.Write("Cookie Expiry Date: " + cookie.Expires.ToLocalTime().ToLongDateString() + " " + cookie.Expires.ToLocalTime().ToLongTimeString() + " <br/>");

    The output generated is:

    Ticket Expiry Date: Saturday, April 05, 20083:00:44 PM
    Cookie Expiry Date: Monday, January 01, 0001 2:00:00 AM 
     

    If however, you check Reflector, you will notice the following code located inside the private OnAuthenticate method: 

                            if (ticket.IsPersistent)
                            {
                                cookie.Expires = ticket.Expiration;
                            }
    
     

     

    What can be said now?

    Thanks

    Bilal Hadiar, MCP, MCTS, MCPD, MCT
    Microsoft MVP - Telerik MVP
Page 1 of 2 (18 items) 1 2 Next >