We're doing a whitelabelled version of our site, which will be hosted at foo.ourdomain.com.
However we need to ensure session is maintained between www.ourdomain.com and foo.ourdomain.com, as our SSL certificate only covers the main domain.
In practice this means we'll swap to the main domain on our payment pages, which run HTTPS, and then redirect back to the subdomain, after payment.
So the question is: How do we maintain the session when doing so ?
I've tried with <httpCookies domain=".ourdomain.com" /> in web.config to no avail :-(
Edit: Figured it out now, I lacked domain on my <forms /> tag to handle login properly.
Like I mentioned in my edit, I just lacked the domain attribute on my tag in web.config.
Related
TL/DR: I am experiencing an HTTP-302 redirect loop when trying to share an authentication cookie between an ASP.NET WebForms site and an ASP.NET MVC web site that are served on separate sub-domains.
Details
a.website.com - The existing WebForms site. Works fine.
b.website.com - The new MVC site I'm trying to integrate using the shared cookie.
User reaches b.website.com and is not yet authenticated. They are redirected to a.website.com/Login.aspx.
User enters their username/password.
The user is redirected to the original desired page on b.website.com.
b.website.com receives the authentication cookie in the request, but for some reason fails to see the user as authenticated. It sends them back to a.website.com/Login.aspx.
a.website.com sees the cookie and realizes the user is authenticated, and redirects the user back to b.website.com.
Steps 4 and 5 repeat until the browser breaks the loop.
Setup
The setup follows the MSDN documentation for Configuring Forms Authentication Across Applications precisely: the two sites share machine key settings and Forms authentication settings. Both sites reside on the same server and IIS instance. Both sites force SSL. In the web.config file, the Membership and RoleManager settings are identical.
For a.website.com, which hosts the login page:
<httpCookies httpOnlyCookies="true" requireSSL="true" />
<authentication mode="Forms">
<forms name="COOKIE_NAME"
domain=".website.com"
loginUrl="login.aspx"
defaultUrl="login.aspx"
requireSSL="true"
cookieless="UseCookies"
protection="All"
enableCrossAppRedirects="true"
path="/"/>
</authentication>
<machineKey
validationKey="((validation key))"
decryptionKey="((decryption key))"
validation="SHA1"
decryption="AES" />
b.website.com is of course pretty similar, except the login URL for unauthorized users directs them to the login on site "a".
<httpCookies httpOnlyCookies="true" requireSSL="true" />
<authentication mode="Forms">
<forms name="COOKIE_NAME"
domain=".website.com"
loginUrl="https://a.website.com/login.aspx"
defaultUrl="login.aspx"
requireSSL="true"
cookieless="UseCookies"
protection="All"
enableCrossAppRedirects="true"
path="/"/>
</authentication>
<machineKey validationKey="((validation key))"
decryptionKey="((decryption key))"
validation="SHA1"
decryption="AES" />
Troubleshooting
This setup works as expected on my development machine and our test server (albeit with no domain setting and loginUrl set accordingly) where both web sites are running from the same domain, just different port numbers. For example, in local development, site "a" might run from https://development:44301/ and site "b" might run from https://development:44302/. However, on the production machine--where they are actually on different subdomains--I experience the redirect loop.
Using the browser web developer tools, I can see that the authorization cookie is being sent to b.website.com after the login redirect. Also on b.website.com, if I remove the [Authorize] attribute decorating the controller, the pages load as expected. I'm reasonably sure the issue is limited to how the MVC site is handling the authentication cookie in the limited subdomain scenario.
It sounds like the same issue was reported on SO here and here, but those users had not set enableCrossAppRedirects="true". That setting (which is enabled in my code) seems to be required for subdomain redirects, as I've already tried. This SO article details the setting a bit more and indicates the redirect should be done via SSL, which I am also doing.
What am I missing? How can I better debug the authentication failure that apparently occurs when site "b" receives but does not acknowledge the cookie?
I finally found an answer, unmentioned in the MSDN documentation I referenced above. Many thanks to Steve Smith's 2-year old blog entry.
The older WebForms site targeted a previous release of .NET, so there is an additional compatibility mode string setting on the machineKey config to handle this. If both applications were the same version, this would be unnecessary.
To be absolutely clear for future searchers-- In the web.config of the older a.website.com WebForms site, targeting an earlier .NET release, I had used an ordinary machinekey setting:
<machineKey
validationKey="((validation key))"
decryptionKey="((decryption key))"
validation="SHA1"
decryption="AES" />
In the web.config of the newer MVC site, I had to also specify the compatibility mode to work with the older site's framework:
<machineKey
compatibilityMode="Framework20SP2"
validationKey="((validation key))"
decryptionKey="((decryption key))"
validation="SHA1"
decryption="AES" />
Note that the compatibility mode string is NOT necessarily the targeted framework of the other app. Any targeted version between 2.0SP2 and 4.5 will need a setting of "Framework20SP2". Check the link above to make sure you're picking the right one!
With this in place (along with the matching forms settings in the original MSDN article), everything worked perfectly.
I foresee myself spending another day figuring out why my authentication is broken when we get around to upgrading the older site's targeted framework!
My Azure cloud service app has users logged in with session data. If they click on a link internally that doesn't have a preceding www, then the session data is not applied. If they go back and click on a link that does have a preceding www, the session data works as expected. Does anyone know how to resolve this?
TIA
Sounds like your session cookies are not tuned to the wildcard of the domain. Can this be a problem? Check the forms section of your web.config if it contains domain attribute and if it doesn't, set it.
<authentication mode="Forms">
<forms loginUrl="/Account/LogOn" timeout="43200" domain="yourdomain.com"/>
</authentication>
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?
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 "".
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.