Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Cookies, Session and switching between plain HTTP and SSL Urls in ASP.NET


:P
On this page:

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>.

Other problems with www.west-wind.com and west-wind.com Cookies

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.


The Voices of Reason


 

Marc Brooks
January 02, 2006

# re: Cookies, Session and switching between plain HTTP and SSL Urls in ASP.NET

Sounds like a job for Global.asax's Application_PreRequestHandlerExecute to me :)

Ric Hossenfus
January 02, 2006

# re: Cookies, Session and switching between plain HTTP and SSL Urls in ASP.NET

We had a similar problem when we started using Akamai - we needed multiple sub-domains (www, secure, media etc), but still needed session, authentication and other cookies to work across all domains.

The way I got around it was to create an HttpModule that resets the Domain of any cookies in Response.Cookies during Application_EndRequest. For example, a cookie with a domain of west-wind.com will work for www.west-wind.com, west-wind.com or horses.west-wind.com.

To make sure the site would still work using localhost, machinename, IP or some other value, I put the domain I want to use for cookies into the web.config and then only reset the domain of cookies if they include that domain. So if my CookieDomain key is 'west-wind.com', the domain on cookies will be reset if requests are made to www.west-wind.com, but not for requests are to www.pony.com or localhost.

Areg Sarkissian
January 02, 2006

# re: Cookies, Session and switching between plain HTTP and SSL Urls in ASP.NET

When you write out the cookie just set the domain property in the response cookie to westwind.com.
Then the cookie will be sent for
westwind.com, www.westwind.com or
anysubdomain.westwind.com

foobar
January 04, 2006

# re: Cookies, Session and switching between plain HTTP and SSL Urls in ASP.NET

Finally, an example that uses the UriBuilder class. Man, that's so much easier than splitting the URL into an array. Good job :)

Kevin
September 29, 2006

# re: Cookies, Session and switching between plain HTTP and SSL Urls in ASP.NET

How would you maintain user credentials say from the ssl'd login page to a non-ssl'd page?

Everything I have tried looses the credentials. (Mind you I am trying to do this via windows/basic auth on the IIS side).
I imagine even in forms auth. the credentials would be lost (at least I think) since the auth cookie was originally created in the ssl space. Now leaving the SSL space good-bye cookie thus goodbye credentials (AKA - principal object tied to page)....?

Rick Strahl
September 29, 2006

# re: Cookies, Session and switching between plain HTTP and SSL Urls in ASP.NET

Kevin, I suspect you would have to do this on a first hit before any authentication takes place. This is the sort of thing you'd have to do right at the beginning of a session by redirecting immediately. In pages this means a custom page class that handles this or an HTTP Handler that deals with the URLs and then redirects.

Kevin
October 02, 2006

# re: Cookies, Session and switching between plain HTTP and SSL Urls in ASP.NET

that was my thought but wanted to bounce it off you. I can pass the credential object in a session variable then I would have to on all page loads stuff the page identity. Fairly safe since no pwd passed except if someone was able to highjack the variable.

Might as well custom page class that or create an HTTP Handler as you mentioned. This would be much better for reuse and code safety. :)

Kalyan
October 11, 2006

# re: Cookies, Session and switching between plain HTTP and SSL Urls in ASP.NET

ok this is a question rather than a comment on this article. I have a similar but strange problem.

I have an asp.net application where i do SSO between 2 application on different machines using cookies, so for this i set the domain name property of the cookie to be the same. I am using forms authentication in the application.

Now when user logs out, i clear session and delete all cookies. Every thing seems to work fine until user does a log out, does a back button and then clicks on some action in the application. Ideally this is supposed to redirect user back to login page, but for some reason this does not happen.

Would any one know cause for the issue?

# DotNetSlackers: Cookies, Session and switching between plain HTTP and SSL Urls in ASP.NET


Jeyaram
November 28, 2006

# Cookies, Session and switching between plain HTTP and SSL Urls in ASP.NET

I'm getting problem when I tried to use this code.

I'm not getting what is that App. (App.Configuration.StoreBaseUrl).
I'm getting the error is 'App' couldn't be found.

Any can help me.

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024