views:

554

answers:

3

Hi.

I have an app with multiple subdomains, subone.parent.com, subtwo.parent.com.

I have a logon page at parent.com/login. When a user logs in I redirect them to the proper domain based on which one they are a member of. This works fine.

FormsAuthenticationTicket ticket = new FormsAuth...
string encTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
cookie.Domain = subone.parent.com
Repsonse.Cookies.Add(cookie)

This properly authenticates the user for subone.parent.com and not subtwo.parent.com. However I would like to do the following.

If the user goes back to parent.com, I would like to know that they are logged in and redirect them back to subone.parent.com.

Is there a best practice for accomplishing this? Or do I have to set another cookie for parent.com?

I'm working in asp.net mvc if it matters.

THanks!

A: 

You can share cookies across domains like you are trying to do, but its not straight forward, example here.

Another options is to set the cookie to be ".parent.com" rather than specifying the sub-domain explicitly and use the cookie store the details of the sub-domain. Then you can access the cookie from any of your sub-domains (and parent assuming its www.parent.com).

If your using MVC, you can pretty easily create a custom filter and add to the www.parent.com controllers to check for the existence of the cookie, and if so redirect to the sub domain the cookie specifies. Further details of fileters here.

RM
I think your second option here may work. I'm setting the domain to the parent. I've added the subdomain to the FormsAuthTicket User data. I have created a CustomIdentity which will on IsAuthenticated will check the current domain against the Userdata. What do you think?
Paul
A: 

I would set the cookie for the explicit domain as you have there because that maintains any security information within that specific domain's cookie. You can also add a non-encrypted cookie at the *.parent.com level that holds information about which domains have been authenticated. There is no real way to tie this together though without using maybe timestamps and having a logical connection between the applications (ie - sub2 has a session timeout of 20 minutes so if the domain + valid timestamp occur in the parent cookie it would be valid, however this is business logic).

I'm not sure the reasoning behind the disconnect between domains, but you might actually prefer to have a single cookie that has encrypted text behind encrypted text. EG:

1) Sub1 logs in, sets the parent.com cookie as valid. Sends a piece of user data to an authentication web service.

2) The authentication service recognizes sub1 as the sender, encrypts the user data, and adds it to a custom cookie object.

3) The custom cookie object constructs a composite string on a unique split character (or sequence) and makes it available to the service method.

4) The service, using the forms encryption, encrypts the entire ticket and sends it back to the original login.

That way each server would be able to unencrypt the global ticket, but each piece of data would be encrypted using a common algorithm but a server based salt. So if sub2 attempts to read the cookie data from sub1, it gets the encrypted version rather than raw data.

Joel Etherton
Thanks, if I add an unencrypted user cookie at the .parent level couldn't that be altered/spoofed to allow access to other subdomains?
Paul
@Paul: Sort of. I'm suggesting 2 levels of encryption. The first is the default FormsAuthentication encryption that keeps your whole cookie private to just the *.parent.com domain. The second is an internal encryption applied to each private section of the cookie whose salt is known only to between the master server and the individual server. Each subdomain would have access to the whole cookie, but they would be unable to decrypt a section belonging to a different subdomain. FormsAuthentication.IsAuthenticated would result in a "true" value.
Joel Etherton
Joel Etherton
A: 

Hi,

you could share the same session on all subdomains. That is the code we use to accomplish that :-)

void MasterPage_Unload(object sender, EventArgs e)
{
   ///ASP.NET uses one cookie per subdomain/domain,
   ///we need one cookie for _all_ subdomains.
   if (Context.Response.Cookies["ASP.NET_SessionId"] == null)
      return;

   var sessionCookie = new HttpCookie("ASP.NET_SessionId", Context.Session.SessionID);
   sessionCookie.Domain = ".yourdomain.com" ; 
   Context.Response.SetCookie(sessionCookie);
 }

inside the Page_Load method is:

 Unload += MasterPage_Unload;

it works great :-)

robert

Robert
Thanks Robert, but I don't want the user to be authenticated on all subdomains, just the one and the root.
Paul