7
votes

My project has problem renewing Forms Authentication Session due to conflicting Forms Auth Cookies.

Detailed Description:

After a user logged in, one forms auth cookie (FACookieA) is created, and s/he is authenticated. When it comes to renew the cookie, however, a second forms auth cookie (FACookieB) is created, and FACookieA is not renewed. The User is redirected to login page on page request after the expiration time in FACookieA, even it is before expiration time in FACookieB.

Generated cookies:

Please note that both cookies have the same name.

FACookieA:

name: FormsAuth
domain: .formsauth.com

please note the "." pre-appended by .NET, the "formsauth.com" is from Forms Authentication Ticket section

FACookieB:

name: FormsAuth
host: a.formsauth.com

please note the cookie uses "host", not domain, and "a.formsauth.com" is based on the current request url domain.

Project url tested:

a.formsauth.com

Web.config:

<forms loginUrl="~/Account/Login.aspx" name="FormsAuth"/>

Code

public partial class Account_Login : System.Web.UI.Page
{   
    protected void LoginButton_Click(object sender, EventArgs e)
    {
        if (Membership.ValidateUser(LoginUser.UserName.Trim(), LoginUser.Password.Trim()))
        {
            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                 1,
                "username",
              DateTime.Now,
              DateTime.Now.AddMinutes(2),
              false,
              string.Empty
              );

            string encryptedTicket = FormsAuthentication.Encrypt(ticket);
            HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
            cookie.Domain = "formsauth.com";
            cookie.Path = FormsAuthentication.FormsCookiePath;
            Response.Cookies.Remove(cookie.Name);
            Response.Cookies.Add(cookie);
            Response.Redirect("~/Account/ChangePassword.aspx"); //authenticated area

        }else
        {
            Response.Write("Invalid UserID and Password");
        }
    }
}

Questions:

1) How to generate one forms auth cookie, so that users can renew forms auth session and will not be logged out?

Considerations:

1) The project needs to support multiple languages, with possible domain formats below:

a.formsauth.com
a.en.formsauth.com
a.us.formsauth.com

and

b.formsauth.com
b.en.formsauth.com
b.us.formsauth.com

Thus, I cannot set the domain attribute of Forms element declaratively. Because two sets of domain cannot share cookie, sharing cookie within one set is allowed. That is the same code base is used for different apps with different domains. But one set of domain can share cookie.

2) The default built-in FormsAuthenticationModule renews user session cookie, which is why I has no control over the domain in the cookie. Please note that FormsAuthenticationTicket is used to create cookie upon use login as shown above.

Any idea?

3
Please post the code that refreshes the cookieMike
did you set cookie.Domain = "formsauth.com"; when you refresh the cookie?Khanh TO
I don't remember ASP.NET Forms Auth too well, so this may not work with your implementation at all, but have you tried adding slidingExpiration="true" cookieless="UseCookies" timeout="x" into <forms > in your web.config? x is the time in minutes of inactivity before the user has to login again.JW Lim
Hi, please see my update.Pingpong
Also, you may want to change your Web.config to: <forms loginUrl="~/Account/Login.aspx" name="FormsAuth" domain="formsauth.com"/> this is to ensure that the default FormsAuthenticationModule will be generating cookies with the same domain instead of the null domain. E.g. FormsAuthenticationModule generates the expired cookie and pushes it to browser. If domain is not set (null), you will be leaving the choice of domain up to browsers. Which may be troublesomeanikiforov

3 Answers

0
votes

You can't mix host and domain cookies with the same name. To make this work all cookies will need to be set at the top level domain.

0
votes

The logic of the code is not very clear, Not clear why you are attempting to replace cookies.)

However I am going to guess that the redirection is happening before the new cookie has been registered.

        Response.Cookies.Remove(cookie.Name);

Add Code here to check if cookie is removed before you try to add the other

        Response.Cookies.Add(cookie);

Add code here to make sure the cookie has been registered by the browser (?), before you redirect

0
votes

Try to use following code.I hope that will help you.

if (Membership.ValidateUser(LoginUser.UserName.Trim(), LoginUser.Password.Trim())) {

                int timeout = model.RememberMe ? 525600 : 30;
                //DateTime timeout = model.RememberMe ? 525600 : 30;
                 string userData = JsonConvert.SerializeObject(model);
                 FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, login[0].adminUserName, DateTime.Now, DateTime.Now.AddMinutes(525600), false, userData);

                string enTicket = FormsAuthentication.Encrypt(authTicket);
                HttpCookie authcookie = new HttpCookie(FormsAuthentication.FormsCookieName, enTicket);
                Response.Cookies.Add(authcookie);



            return  Response.Redirect("~/Account/ChangePassword.aspx"); //authenticated area


            }
            else
            {
                Response.Write("Invalid UserID and Password");
            }