I have a web app can be installed on lots of domains and paths.
So:
All separate application instances of the same code.
The problem is that if a client logs in to client1Name.{mySite.com} then visits one of the other sites their browser will send the authentication cookie.
In all cases FormsAuthentication.SetAuthCookie
doesn't set either the Path
or the Domain
.
What I would expect is:
Domain
= client1Name.{mySite.com} Path
= /Domain
= client2Name.{mySite.com} Path
= /Domain
= demo.{mySite.com} Path
= /prospect1Name Domain
= demo.{mySite.com} Path
= /prospect2Name Domain
= demo.{mySite.com} Path
= /prospect3Name I can manually override .Net's behaviour to explicitly set these, but I'm not sure why I should need to - sure this should be the default behaviour when setting an authentication cookie or at least an option that can be set without re-writing big chunks of it.
Am I missing something? Is there some way to make FormsAuthentication.SetAuthCookie
set the Path
and Domain
?
If not what is the best way to dynamically read the best Path
and Domain
? The same code has to run on all sites and I don't want to add a further configuration key.
Update
Here is my current solution:
// replacement for FormsAuthentication.SetAuthCookie(user.UserName, false);
// as that fails to limit the cookie by domain & path and fails.
var cookie = FormsAuthentication.GetAuthCookie(username, false);
cookie.HttpOnly = true;
cookie.Path = this.Request.ApplicationPath;
cookie.Secure = string.Equals("https", this.Request.Url.Scheme, StringComparison.OrdinalIgnoreCase);
// the browser will ignore the cookie if there are fewer than two dots
// see cookie spec - http://curl.haxx.se/rfc/cookie_spec.html
if (this.Request.Url.Host.Split('.').Length > 2)
{
// by default the domain will be the host, so www.site.com will get site.com
// this may be a problem if we have clientA.site.com and clientB.site.com
// the following line will force the full domain name
cookie.Domain = this.Request.Url.Host;
}
this.Response.Cookies.Add(cookie);
However, that seems like a lot of workaround for something FormsAuthentication.SetAuthCookie
should be able to do. Is this really the best way?
I've had to do a lot of digging, but is looks like the reason FormsAuthentication.SetAuthCookie
doesn't support this is because it shouldn't - IIS should never set paths on authentication cookies, and here's why...
Cookie paths are case-sensitive, so:
http://site/path
http://site/PATH
Are 2 different cookies for the browser - none of them (IE, FX, Safari, Opera or Chrome) will send /PATH
's cookie to /path
or vice versa.
IIS is case-insensitive, but will always reset the URL to the ASP application name's case.
This means that if the IIS application is called "PATH" and the user goes to http://site/path
then they will be redirected to log-on at http://site/PATH/LogOn?ReturnUrl=/path
by IIS/ASP.Net
After a successful log-on the user gets redirected back to the ReturnUrl
specified, so:
http://site/path
http://site/PATH/LogOn?ReturnUrl=/path
by IIS/PATH
and the location to /path
(as defined by ReturnUrl
)http://site/path
/path
, it only has a cookie for /PATH
and so sends nothing!http://site/PATH/LogOn?ReturnUrl=/path
This creates a problem for users if they have http://site/path
as the URL for the application they will never appear to be able to log-on.
Further to this if they're already logged on to http://site/PATH
and get sent a URL, say an email to a http://site/path/resource/id
, they will get asked to log on all over again and won't be able to get to the new path.
This means that unless you need /PATH
and /path
to be completely different sites (unlikely outside certain UNIX only environments) you should never set the path property on authentication cookies.