views:

597

answers:

4

I am using Visual Studio Team System 2008 (VSTS), C#, .NET 3.5, IIS 7.0, and ASP.NET. I have two IIS web sites, site A and site B. Their related domain names are, http://sitea.example.com and http://siteb.example.com.

I heard when using Form authentication, we could enable domain level cookies, that is, if two sites are in the same domain (e.g. both sitea.example.com and siteb.example.com are in domain example.com), the end user only needs to authenticate once. In more details, if the user is authenticated (passed authentication) by one of the sites, there is no need to authenticate the user again in the other sites.

How this feature be enabled for my sitea and siteb? Do I need to change the web.config for both sitea and siteb?

Another confusion is, if the user is authenticated by sitea, it is sure that the user's identity is recognized by sitea, but how could siteb recognize the user's identity without authenticating the user again?

+2  A: 

This link give some details http://docs.communityserver.com/2007/270-common-things-to-check-when-using-forms-authentication/

Basically you need to add the domain attribute in the <forms/> tag within the <authentication> tag of the web.config file.

e.g.

<authentication mode="Forms">
<forms name=".CookieName" ... domain=".mydomain.com" />
</authentication>
Jonathan Parker
Another issue is, I am not using the built-in database provider for Forms authentication, I am using a customized authentication method (I wrap my customized authentication method into a DLL and expose the authentication method, if authentication pass, I will set authentication pass cookie.) I am not sure if I am using such customized authentication method, I can still use domain level cookie for Forms authentication?
George2
+1  A: 

Set the domain attribute to .mycorp.com in the form tag in the web.config

Chuck Conway
Another issue is, I am not using the built-in database provider for Forms authentication, I am using a customized authentication method (I wrap my customized authentication method into a DLL and expose the authentication method, if authentication pass, I will set authentication pass cookie.) I am not sure if I am using such customized authentication method, I can still use domain level cookie for Forms authentication?
George2
+8  A: 

Assuming both sites share the same membership database then you can set the cookie domain in the forms authentication section of web.config;

<authentication mode="Forms">
    <forms .... domain="mycorp.com"/>
</authentication>

Note that you'll also have to setup matching machine keys in the web.config as these are used to sign the authentication cookie.

blowdart
1. Should both web site using the same machine key? 2. Another issue is, I am not using the built-in database provider for Forms authentication, I am using a customized authentication method (I wrap my customized authentication method into a DLL and expose the authentication method, if authentication pass, I will set authentication pass cookie.) I am not sure if I am using such customized authentication method, I can still use domain level cookie for Forms authentication?
George2
1. Yes.2. If you are using the forms authentication cookie sure. If you're using your own cookie, and set the domain on the cookie it will work as expected.
blowdart
Using authentication cookie you mean something like these -- "Dim C As System.Web.HttpCookie = _ Request.Cookies(System.Web.Security.FormsAuthentication.FormsCookieName)C.Domain = "example.com"C.Expires = DateTime.Now.AddDays(-1)Response.Cookies.Add(C)"
George2
I am interested in "If you're using your own cookie, and set the domain on the cookie it will work as expected", could you show me how to set an arbitrary application cookie (no need to be Forms authentication cookie) as domain wide please?
George2
I'd suggest that deserves a question of it's own, so other people can find it - http://msdn.microsoft.com/en-us/library/ms178194.aspx has the details.And yes, for the forms auth cookie, just like that. Except not with an expiry date in the past - that cookie would never work!
blowdart
A: 

I would suggest the way Stack Overflow, Microsoft, Facebook, Google Accounts do, and that is even more efficient because every website can be on any different machines.

Assume, you have AuthSite. This is the one site where you have to login, and has membership information.

And you have SiteA, SiteB, and SiteC on different servers.

On login page of SiteA you have to setup a form post with a secret on AuthSite.

If you had previously logged successfully on AuthSite, it will just redirect back to SiteA with successful secret in the form of a hidden Form Post in the browser, that you have to verify in SiteA.

This model is highly extensible and scalable. Because maintanence in the long run is easy.

Code on LoginPage of SiteA, SiteB and SiteC follows.

Login.aspx on SiteA, SiteB, and SiteC:

private void Page_Load(object sender, EventArg e){
   // Simply redirect back to AuthSite...
   // Change Site parameter accordingly.
   Response.Redirect("http://authsite/Login.aspx?Site=SiteA");
}

Login.aspx on AuthSite:

// Define one hidden field named "ReturnSite".

private void Page_Load(object sender, EventArg e){

   if(IsPostBack)
       return;
   string site = Request.QueryString["Site"];
   if(Request.User.IsAuthenticated){
       string secrete = CreateSomeSecrete(site);
       Response.Redirect("http://" + site + 
           "/AuthConfirm.aspx?Token=" + secrete + 
           "&User=" + Request.User.Identity.Name);
       return;
   }

   ReturnSite.value = site;
   // Do usual login...
}

private void LoginButton_Click(object sender, EventArg e){
   string secrete = CreateSomeSecrete(ReturnSite.value);
   FormAuthentication.SetAuthCookie(username,true);
   // You can retrive username later by calling 
   // Request.User.Identity.Name.
   Response.Redirect("http://" + ReturnSite.value + 
      "/AuthConfirm.aspx?Token=" + secrete + "&User=" + username);
}

AuthConfirm.aspx on SiteA, SiteB, and SiteC:

private void Page_Load(object sender, EventArg e){
   string secrete = Request.QueryString["Token"];
   // Verify that secret came only from AuthSite.
   if(VerifySecrete(secrete)){
       // This sets authentication cookie for Current Site
       FormsAuthentication.SetAuthCookie(Request.QueryString["User"], true);
   }
}

Now let's see a different scenario.

Same User, First time login

  1. The first user, John, visiting SiteA (not yet logged in) gets redirected to AuthSite.
  2. AuthSite checks and finds out that user does not have an authentication cookie, so actual credentials are asked.
  3. AuthSite sets token on itself and passes secret to AuthConfirm page on SiteA. SiteA verifies the token and sets the authentication cookie and lets user to visit secure pages.

Same User, First time on SiteB

  1. User John is successfully logged into SiteA using AuthSite, now tries to visit SiteB.
  2. SiteB finds the user is not logged in so it is directed to AuthSite.
  3. AuthSite finds that the user already has a cookie for AuthSite website.
  4. AuthSite redirects user back to SiteB with the authentication secret.
  5. SiteB verifies the secret and lets John continue to visit secure pages.
Akash Kava
Thanks! But I did not find how your scenario works in this scenario -- an un-authenticated user goes to SiteB, and redirect to SiteA for authentication, and how SiteA, SiteB and SiteC which are of different domain shares the same authentication information (e.g. if user passed authentication in one of the sites, the user has no need to authenticate again with other sites). Appreciate if you could provide more information about this. Thanks again!
George2
If Unauthenticated user goes to SiteA, SiteB or SiteC, he is redirected to AuthSite (AuthSite is a seperate site, like Microsoft Passport, OpenID used by StackOverflow, Facebook Connect). I will try to illustrate an example.
Akash Kava
You're talking about federation, which, when all the sites are within the same domain is very much overkill
blowdart