I ran into some real nastiness with cookies and domain name attachments today. One of my customers mentioned that in one of our applications the switch to a secure links caused the Session to basically dump all items that were previously set. This particular app is a custom West Wind Web Store app, and it would basically dump the user attachment that was stored in a session object.
The problem occurs whenever a user comes into the store with a URL that is west-wind.com instead of www.west-wind.com. Now IE automatically fixes up this problem – Mozilla and other browsers do not.
As you probably know, Cookies are stored by exact domain name and virtual so technically west-wind.com and www.west-wind.com are two separate domains. So if you go to the site one day with www.west-wind.com and then come back another with west-wind.com your stored Id is no longer there…
Ok, that’s nothing new. In my code I used some simple logic to flip people from a straight URL to an SSL Url originally using some simple string translation. Every app I have stores a domain name and a logical base path from which a URL can be easily built. So if switching to SSL I’d just use HTTPS and that was that. But this backfired because the domain name was hardwired. So I’d go to: https://www.west-wind.com/wwstore/somepage.aspx but when the user came in under west-wind.com, he’d immediately loose his Session cookie because in the switch.
So I figured I can do something a little more dynamic using the Uri and UriBuilder class in the ASP.NET page using C# codebehind at the bottom of the page’s Page_Load():
// *** Fix up the order button to turn the current link into an SSL link
if (App.Configuration.UseSecureOrderLink)
{
UriBuilder Builder = new UriBuilder(Request.Url);
Builder.Scheme = Uri.UriSchemeHttps;
Builder.Port = 443;
Builder.Path = App.Configuration.StoreBaseVirtual + "orderprofile.aspx";
this.hypOrderFormLink.NavigateUrl = Builder.Uri.ToString();
}
This code gets the original Url then strips off and modifies the pieces I’m interested in and spits it back out. Code works just fine in getting the URL fired into HTTPS. However, there’s another really big problem with this…
If you have a secure certificate that certificate is typically bound to a specific domain name like www.west-wind.com. Switching to west-wind.com actually causes a certificate warning dialog to pop up.
Worse though, on the other side of that warning dialolg the Session Cookie gets lost! So even though I now go to https://west-wind.com/wwstore/correctPage.aspx that page does not work correctly because the Session Cookie has been blown away. I’m not sure why this happens but this happens both in IE and FireFox.
So you can’t just ensure that your URL gets fixed up properly you basically have to make sure that as soon as the user comes to your site they use a consistent domain name which should be the same domain name that’s on your certificate.
In the end I had to write some code that checks the Url hostname on every request and makes sure it matches the application’s official host name. If it doesn’t match it redirects the page using the full host name.
I added this code to my page base class used in all the front end pages of the application.
protected override void OnInit(EventArgs e)
{
// *** Make sure users always come in using the full domain name
// *** this is necessary to ensure that switching to SSL works reliably...
Uri WebHost = new Uri(App.Configuration.StoreBaseUrl);
if (Request.Url.Host != WebHost.Host)
{
UriBuilder NewUrl = new UriBuilder(Request.Url);
NewUrl.Host = WebHost.Host;
string TA = NewUrl.Uri.ToString();
Response.Redirect( NewUrl.Uri.ToString() );
}
base.OnInit(e);
}
The code relies on a configuration setting (StoreBaseUrl) that I pretty much use in every app (actually more recently I store a domainname) that I use to get a base reference. Above this is something like http://www.west-wind.com/wwstore/.
The code above does the trick even though it seems a bit heavy handed to have to look at every request. In this particular app most pages can be directly accessed, so I need to do this on a more or less Global basis here. If your app has a single entry point such as a Default or Login page then it would be better to put this code there…
The other downside to this hack is that if the user forgets to set up the domain name or base url, the site will redirect to some default site which may cause some confusion. If you do this make sure that any configuration pages you might use to let the user configure this setting is exempt from this translation <g>.
While I was poking around with this I ran into one other really nasty issue: If you have multiple domains that have accessed your app and store a permanent cookie, Internet Explorer will store both cookies separately on disk. www.west-wind.com and west-wind.com each get their own cookie files. However, if you go to either of the sites explicitly Internet Explorer returns – BOTH Cookies. How freaking lame is that?
FireFox correctly returns only the appropriate cookie thankfully, but that doesn’t help for a public app.
Just another thing to watch out for. I realize now that this has been the bug that’s been driving me crazy with several applications, especially in the West Wind Web Store where in some odd situations I would not be able to reattach to my profile because there’d be two cookies stored on disk and the WRONG one would be read causing a user lookup to fail. This explains a lot of freaky behavior that I haven’t been able to track down… Especially since one of my sub sites – the Web Log using .TEXT – insists on referencing my domain without the www prefix…
It’s time to replace the funky .TEXT code… soon.
Other Posts you might also like