1
votes

I'm noticing some strange behavior with a shared authentication cookie setup, here's my scenario.

I've got two applications with the domains similar to the following:

login.mydomain.com system.mydomain.com

I am redirecting the user to login.mydomain.com and dropping a the cookie from there on mydomain.com like so.

system.mydomain.com:

void Application_AuthenticateRequest(object sender, EventArgs e)
    {
        if (Context.User == null || !Request.IsAuthenticated)
        {
            HttpContext.Current.Response.Redirect("http://login.mydomain.com");
        }
    }

login.mydomain.com

protected void btnSubmit_Click(object sender, EventArgs e)
    {
        pnlLoginNotice.Visible = true;
        if (Membership.ValidateUser(txtUsername.Text, txtPassword.Text))
        {
            HttpCookie cookie = FormsAuthentication.GetAuthCookie(txtUsername.Text, chkRememberMe.Checked);
            cookie.Domain = "mydomain.com";

            Response.Cookies.Set(cookie);
        }
    }

Web.config:

<authentication mode="Forms" >
  <forms timeout="2880" name=".COMMONAUTH"  />      
</authentication>

Now the behavior I'm seeing is that I'm finding the .COMMONAUTH cookie dropped under system.mydomain.com sometimes, while there's the same cookie under mydomain.com. I've noticed that it shows up after some time of inactivity on the site.

Is it possible that asp.net is dropping the cookie on it's own to keep the forms authentication alive?

UPDATE I've tried the following approaches

1:

system.mydomain.com Web.config

<authentication mode="Forms" >
  <forms timeout="1" name=".COMMONAUTH" />      
</authentication>

login.mydomain.com Web.config

<authentication mode="Forms" >
  <forms timeout="2"  name=".COMMONAUTH"/>
</authentication>

When refreshing a page in system.mydomain.com after one minute has passed, I get the .COMMONAUTH cookie under system.mydomain.com

2:

system.mydomain.com Web.config

<authentication mode="Forms" >
  <forms timeout="2" name=".COMMONAUTH"  />      
</authentication>

login.mydomain.com Web.config

<authentication mode="Forms" >
  <forms timeout="1"  name=".COMMONAUTH"/>
</authentication>

When refreshing a page in system.mydomain.com after one minute has passed, I get logged out.

3:

system.mydomain.com Web.config

<authentication mode="Forms" >
  <forms timeout="1" name=".COMMONAUTH" domain="mydomain.com" />      
</authentication>

login.mydomain.com Web.config

<authentication mode="Forms" >
  <forms timeout="2"  name=".COMMONAUTH" domain="mydomain.com"/>
</authentication>

When refreshing a page in system.mydomain.com after one minute has passed, all remains the same and I'm still authenticated. Not sure what will happen when a 3rd application will be introduced to this setup

Conclusion

I think my issue is comming from not setting the domain in the web.config, so system.mydomain.com is trying to refresh the cookie but is using its own domain since I am not telling it where it should be doing it.

My problem is that these applications will have different domain bindings and they will be hosted once for multiple clients. I cannot set FormsAuthentication.CookieDomain as it is read only.

Should I go with option 2, and give my cookie issuer a lower timeout from the other applications? Will this have any implications?

2

2 Answers

1
votes

With the information you provided, you also have the option to modify dynamically your configuration in the Application_Start to set the correct value for the domain attribute if it is not already set :

See :

http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k%28System.Configuration.ConfigurationManager%29;k%28TargetFrameworkMoniker-.NETFramework

Hope this will help


I guess an hint can be found in the timeout attribute description of the forms element:

http://msdn.microsoft.com/en-us/library/1d3t3c61%28v=vs.80%29.aspx

To prevent compromised performance, and to avoid multiple browser warnings for users who have cookie warnings turned on, the cookie is updated when more than half of the specified time has elapsed. This might cause a loss of precision. The default is "30" (30 minutes).

is it also set to 2880 minutes on system.mydomain.com ? or is it the default 30 minutes value ? if so, you should see a cookie change after 15 minutes.


Does the problem still happen if you set up your web.config like this ?

<authentication mode="Forms" >
  <forms timeout="2880" name=".COMMONAUTH" domain=".mydomain.com" />      
</authentication>
1
votes

I ended up doing this, I won't mark this as the answer just yet, jut in case anyone points out any issues with it.

In Global.asax

void Application_AuthenticateRequest(object sender, EventArgs e)
    {
        if (Context.User == null || !Request.IsAuthenticated)
        {
            HttpContext.Current.Response.Redirect(GetLoginUrl());
        }
        else if (Context.User.Identity is FormsIdentity)
        {
            HttpCookie cookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];

            if (cookie != null)
            {
                FormsAuthenticationTicket currentTicket = FormsAuthentication.Decrypt(cookie.Value);


                if (currentTicket == null && currentTicket.Expired)
                {
                    return;
                }
                FormsAuthenticationTicket newTicket = currentTicket;
                if (FormsAuthentication.SlidingExpiration)
                {
                    FormsIdentity id = (FormsIdentity)Context.User.Identity;
                    newTicket = FormsAuthentication.RenewTicketIfOld(id.Ticket);
                }

                if (currentTicket != newTicket)
                {
                    cookie.Value = FormsAuthentication.Encrypt(newTicket);
                    cookie.Expires = newTicket.Expiration;
                    cookie.Domain = WebGlobal.GetCurrentContextDomain();

                    Response.Cookies.Set(cookie);
                }
            }
        }
    }