Forms Authentication across Sub-Domains - c#

Is it possible to authenticate users across sub-domains when the authentication takes place at a sub-domain instead of the parent domain?
For example:
User logs into site1.parent.com, and then we need to send them to reporting.parent.com.
Can I authenticate them to the reporting site even though the log-in occured at a sub-domain?
So far all of the research I have done has users logging into the parent domain first and then each sub-domain has access to the authentication cookie.

When you authenticate the user, set the authentication cookie's domain to the second-level domain, i.e. parent.com. Each sub-domain will receive the parent domain's cookies on request, so authentication over each is possible since you will have a shared authentication cookie to work with.
Authentication code:
System.Web.HttpCookie authcookie = System.Web.Security.FormsAuthentication.GetAuthCookie(UserName, False);
authcookie.Domain = "parent.com";
HttpResponse.AppendCookie(authcookie);
HttpResponse.Redirect(System.Web.Security.FormsAuthentication.GetRedirectUrl(UserName,
False));

You can set the cookie to be the parent domain at authentication time but you have to explicitly set it, it will default to the full domain that you are on.
Once the auth cookie is correctly set to the parent domain, then all sub-domains should be able to read it.

As a side note, I found that after using jro's method which worked well +1, the FormsAuthenication.SignOut() method didn't work when called from a subdomain other than www/. (I'm guessing because the .Domain property doesn't match) - To get around this I used:
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
HttpCookie myCookie = new HttpCookie(FormsAuthentication.FormsCookieName);
myCookie.Domain = "parent.com";
myCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(myCookie);
}

In addition to setting a cookie to parent domain also need to make sure that all sites (apps) have same validationKey and decryptionKey () so they all recognise each other's authentication ticket and cookie. Pretty good article here http://www.codeproject.com/KB/aspnet/SingleSignon.aspx

Jro's answer works fine. But make sure to update the webconfig forms authentication setting "domain"
, otherwise forms authentication signout will not work properly. Here is the signout issue I came across. Trick here is to have a '.' as the prefix as the domain is set for the cookie as ".parent.com" (use a cookie inspector).
<authentication mode="Forms">
<forms cookieless="UseCookies" defaultUrl="~/Default" loginUrl="~/user/signin" domain=".parent.com" name="FormAuthentication" path="/"/>
</authentication>

Yes, sure. You may need to roll your own at some stages, but it should be doable.
One idea: as you redirect them across the boundary, give them a one-time pass token and then tell the receiving sub-domain to expect them (this user, from this IP, with this token).

2 things to be done:
MachineKey should be same in all web.config (main domain and sub domain(s))
AuthenticationCookie domain name should be same.
Follow the following article for more depth.

Related

I want to mod how IE generates cookies

There are two different websites that people use, let's call them A and B. Now, as far as login page goes, A and B are nearly identical in design, but the user account logins for A and B are stored in separate datatables and information is different. When someone logs into A, IE will store their info in a cookie and will call it when going on B, even though they are not the same. Nowhere in the login web forms can I find code for generating the cookie, so I am assuming that everything is done within IE. I found the file 'index.dat' that supposedly stores all of IE's cookies in each user's AppData folder, but I do not know how to access it, let alone change the way IE stores the cookies.
My goal is for IE to have distinct cookies for A and B.
Place the sites on different domains. If the sites share a domain, they will see each other's cookies. You can't change this. It's how cookies work.
So I suppose you want to change default asp.net forms authentication cookie names to something else.
Something like this in web.config:
<authentication mode="Forms">
<forms name="myCustomCookieForApp1" ... />
</authentication>
You can read up here:
http://msdn.microsoft.com/en-us/library/ff647070.aspx
The only way IE will send the cookie for A to B is if they are on the same domain and you haven't configured the login mechanism to limit the cookie to your subdomain.
See sub-domain cookies, sent in a parent domain request?

C#/ASP.NET MVC: how to register/log in a different web application if I know username & password?

I have a primary web app with authentication on example.com, and I have a secondary app with authentication on subdomain.example.com
I want the 2nd app to be integrated with the first one. So once a user registers and logs in, s/he doesn't have to register/log in again.
It is possible to send a post request, but this won't generate the cookies in user's browser...
How can I do that?
Thanks
You're able to set a cookie so that it works on all subdomains (www, subdomain, etc.). See Basics of Cookies in ASP.NET:
By default, cookies are associated with a specific domain. For example, if your site is www.contoso.com, the cookies you write are sent to the server when users request any page from that site. (Except for cookies with a specific path value, as I explained in the section immediately preceding.)
You can also use the Domain property to create a cookie that can be shared among multiple subdomains. For example, set the domain as follows:
Response.Cookies("domain").Value = DateTime.Now.ToString
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
Response.Cookies("domain").Domain = "contoso.com"
The cookie will then be available to the primary domain as well as to sales.contoso.com and support.contoso.com.

ASP.NET Authentication cookie

On an application that has form based authentication, I have a standard ASP.NET Login control with the following Authenticate event handler.
void Login_Authenticate(object sender, AuthenticateEventArgs e)
{
if (Security.AuthenticateUser(Login.UserName, Login.Password))
{
e.Authenticated = true;
RedirectFromLoginPage(Login.UserName);
}
else
{
e.Authenticated = false;
}
}
The RedirectFromLoginPage function goes like this :
private void RedirectFromLoginPage(String username)
{
String returnUrl = GetReturnUrl();
FormsAuthentication.SetAuthCookie(username, true, "/");
Response.Redirect(returnUrl, true);
}
This works fine in 99% of cases. However, I sometimes get support calls from people who can't log in. They will enter their credentials, get redirected back to the home page (which is what happens when everything works fine) but they won't be logged in.
Figuring it might be a cookie problem, I tried to reproduce the problem in my environment by setting my privacy options to "Block All Cookies" and I was able to reproduce the problem. The SetAuthCookie function is called, but on the next page load HttpContext.Current.User.Identity.IsAuthenticated returns false.
In my web.config, the authentication is set like so :
<authentication mode="Forms">
<forms loginUrl="..." timeout="180" cookieless="AutoDetect"/>
</authentication>
Reading the documentation on MSDN about AutoDetect and SetAuthCookie, I got that :
AutoDetect Specifies that cookies are
used, if the device profile supports
cookies; otherwise, cookies are not
used.For desktop browsers that are
known to support cookies, a probing
mechanism will be used to try to use
cookies, when enabled. If a device
does not support cookies, no probing
mechanism will be used.
FormsAuthentication.SetAuthCookie :
Creates an authentication ticket for
the supplied user name and adds it to
the cookies collection of the
response, using the supplied cookie
path, or using the URL if you are
using cookieless authentication.
I would of thought that in my scenario, cookieless authentication would of been used but it isn't (I don't see anything in the QueryString after the redirect anyway).
If I set a breakpoint in the RedirectFromLoginPage function and test some values I get :
bool cookieSupport = Request.Browser.Cookies; //"true"
bool redirectWithCookies = Request.Browser.SupportsRedirectWithCookie; //"true"
HttpCookieMode currentMode = FormsAuthentication.CookieMode; //"AutoDetect"
I'm not sure if the Request.Browser.Cookies is meant to be true or not here. The browser does support cookies, but they are all blocked...
Anyway, I got to remote for a few minutes on a machine where the problem was happening. The privacy settings were set to medium so it should of been able to accept cookies. It was a standard Win7 / IE8 setup. I tried adding the website to the user's trusted zone, to login via https but it didn't work. Other problem setups were similar (nothing really stands out with the machines and the users tell me they have no problems on other websites)
So what am I doing wrong here?
Do you specify the domain for the forms authentication cookie in the web.config file? And does it match the domain for the website?
I believe Medium security settings in IE block third party cookies so the problem could be IE thinking your authentication cookie is a third party cookie.
A similar problem occured for me. But it was only for Internet Explorer 8. After some research, I figured that IE8 runs on cookiless mode by default. So, I changed this line in web.config:
<forms loginUrl="..." timeout="180" cookieless="AutoDetect"/> to
<forms loginUrl="..." timeout="180" cookieless="UseUri"/>, and it works fine.

Windows Identity Foundation Security Token Service can't stay logged in

I'm using the Windows Identity Foundation (WIF) Security Token Service (STS) to handle authentication for my application which is working all well and good. However I can't seem to get any long running login with the STS.
From my understanding I shouldn't care about the client tokens at the application level since they can expire all they want to and it should redirect me to the STS and as long as they're still logged in on the STS it should refresh their application token. Yet it doesn't seem to want to keep them signed in.
Here's what occurs in my login.aspx on the STS
var cookie = FormsAuthentication.GetAuthCookie(userName, persistTicket);
if (persistTicket)
cookie.Expires = DateTime.Now.AddDays(14);
Response.Cookies.Add(cookie);
var returnUrl = Request.QueryString["ReturnUrl"];
Response.Redirect(returnUrl ?? "default.aspx");
Which was taken almost directly from existing application using normal Forms Auth.
From my web.config
<authentication mode="Forms">
<forms loginUrl="Login.aspx" protection="All" timeout="2880"
name=".STS" path="/" requireSSL="false" slidingExpiration="true"
defaultUrl="default.aspx" cookieless="UseDeviceProfile"
enableCrossAppRedirects="false" />
</authentication>
Looking at the cookie after I sign in I can see the expires time on the cookie is set for 14 days in the future and that the cookie is NOT a session cookie.
When I'm required to log back into the STS I can see that my original cookie is still there.
Is there some kind of time stamp functionality that the STS embeds into the cookie that is invalidating my cookie even though as far as I know it should still be valid?
After reading the suggestion from #uosel this lead me down the path of doing more indepth analysis on what exactly is occurring here. Whereas my goal is to create a persistent cookie only for the STS itself and not for the STS consuming sites. This way I can always validate the user at the STS level at any expiration of a STS consuming site.
With more locomotion in this train of thought it dawned on me that the STS starter site uses forms auth to secure the actual WIF authorization that occurs in the index.aspx. That the issue was I had no logic that would use an existing forms auth ticket to process the transfer to the forms auth secured index page.
This lead me to a solution similar to
if(User.Identity.IsAuthenticated)
{
if(IsValidUserCredentials())
{
var returnUrl = Request.QueryString["ReturnUrl"];
Response.Redirect(returnUrl ?? "default.aspx");
}
}
else
{
DisplayLoginForm()
}
If you are using passive redirects, do you have persistentCookiesOnPassiveRedirects set to true?
<wsFederation passiveRedirectEnabled="true"
persistentCookiesOnPassiveRedirects="true" />

ASP.NET MVC - cross sub domain authentication/membership

Hit a roadblock while implementing a sub domain based language switcher (en.domain.com loads English, jp.domain.com loads Japanese).
How do I get a single membership system to work across multiple sub domains (ASP.NET MVC C#)?
Saw something about adding domain="domain.com" to <forms > entry in web.config. Did that, but does that work when testing on local visual studio development web server?
Try creating the cookie yourself.
In AccountController you'll find this:
FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
that "creates and adds to the cookie collection". It doesn't allow modification of the domain (but does allow modification of the path, oddly). Instead create a cookie without adding to the collection, modify the necessary properties, then add to the collection:
var a = FormsAuthentication.GetAuthCookie(userName, createPersistentCookie);
//if you're debugging right here, a.Domain should be en.example.com; change it
a.Domain = "example.com";
HttpContext.Current.Response.Cookies.Add(a);
James
You have to use dot prefix, like this.
<authentication mode="Forms">
<forms domain=".tv.loc" loginUrl="~/signin" timeout="2880" name="auth" />
</authentication>
Your problem is how browsers sends cookie during request.
Cookie is generally tied to a single domain, this is for security reasons and performance. For example, user don't want to send cookie for your domain to any other domain, because your cookie may contain sensitive information.
Browser do differentiate between cookies set with en.domain.com and jp.domain.com. They do not allow cookies from one domain goes to the other because they are not on a parent domain.
The solution to your problem would be to take over the control of generating cookies. I haven't played much with ASP.NET MVC, but I'm sure it can be done not through the HTML but through a property or something. This is a very common scenario. You should set the cookies domain to "domain.com" for your production boxes, that is correct. If you're working on a local box, you should set the cookies domain to "".

Categories

Resources