ASP.NET: Loss of Session / Cookies with Frames
Imagine if every Thursday your shoes exploded if you tied them the usual way. This happens to us all the time with computers, and nobody thinks of complaining. -- Jef Raskin
Recently we had a forum question on eggheadcafe.com where the user indicated they were losing Session because of the use of FRAMESET or an IFRAME.
If you implement a FRAMESET where frames point to other Web sites on the networks of your partners or inside your network, but you use different top-level domain names, you may notice in Internet Explorer 6 that any cookies you try to set in those frames are lost. This is most frequently experienced as a loss of session state in an Active Server Pages (ASP) or ASP.NET Web application. You try to access a variable in the Session object that you expect to exist, and it is null. You can also see this problem in a FRAMEs context if your Web pages alternate between the use of Domain Name System (DNS) names and the use of Internet Protocol (IP) addresses.
The fix is very simple - Starting in Internet Explorer 6 support for the Platform for Privacy Preferences (P3P) Project was introduced. The P3P standard notes that if a FRAMESET or a parent window references another site inside a FRAME or inside a child window, the child site is considered third party content. Internet Explorer, which uses the default privacy setting of Medium, silently rejects cookies sent from third party sites. So consequently a large percentage of your visitors may end up having an unhappy experience on your site.
You can add a P3P compact policy header to your child content, and you can declare that no malicious actions are performed with the data of the user. If Internet Explorer detects a satisfactory policy, then Internet Explorer permits the cookie to be set. Most developers that have hosted sites don't have the ability to access IIS and set the required header.
An easy fix is to add the header in Global.asax:
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("p3p", "CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"");
}
A simple compact policy that fulfills the needed criteria follows:
P3P: CP="CAO PSA OUR"
The above code sample shows that your site provides you access to your own contact information (CAO), that any analyzed data is only "pseudo-analyzed", which means that the data is connected to your online persona and not to your physical identity (PSA), and that your data is not supplied to any outside agencies for those agencies to use (OUR). This is sufficient to get Internet Explorer (and some other browsers) to allow the Session cookie, as well as other cookies.
This page provides more information about the P3P privacy policy for Internet Explorer.
To summarize: unsatisfactory cookies are those where the policy contains a token from both columns in the table below and where the purpose/recipient token does not contain the optional attributes, "i" or "o." As an example, a cookie with a compact policy that contains the tokens PHY and OTR is an unsatisfactory cookie, whereas a cookie with the compact policy that contains PHY and OTRo is acceptable.
Category | Purpose/Recipient |
---|---|
PHY Physical location ONL Online location GOV Government ID FIN Financial information | SAM Same policies OTR Other recipients UNR Unknown purposes PUB Publicly available IVA Individual Analysis IVD Individual Decision CON Contact Information TEL Telephone Promotion OTP Other Purposes |
If you've been having Session or other cookie issues and you have any kind of frames on your pages, try this fix. Even if it does not solve the problem, it cannot hurt.
NOTE: This fix will NOT fix the security issue with denied access to content in an IFRAME or FRAME whose content is loaded from a different domain. That is by design, and I've railed about how hypocritical it is since you can have a client-side script tag whose src property points to anywhere at all, and browsers will happily slurp it up. That's why so many developers have turned to dynamically written script tags using JSON to marshal their results back into the browser DOM in the page.
Thanks for this. Excellent timing, I've been wrestling with the problem for a couple of days and this has fixed it! :)
ReplyDeleteVery valuable information! Thanks alot for sharing!
ReplyDeleteThanks for the great article.
ReplyDeleteBut how do I implement this for ASP pages?
What I do now is to add the third-party site to the sites allowed to use cookies in IE. This allows the webpage called in the frame to work properly with sessions/cookies.
Thankyou, thankyou, thankyou!
ReplyDeleteThis little snippet saved me a lot of wasted time and effort (and a potential redesign of my architechture!)
By the way to implement in classic ASP use this:
Response.AddHeader "p3p", "CP=\""IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"
Works a charm!
Did I say thanks by the way!
GS
Perfect timing for me as well. I've been wrestling with this for the past 3 days wondering where my code went wrong with just IE and not Firefox.
ReplyDeleteThanks!
Hi,
ReplyDeleteThanks alot!!! Really helpful!
For people who need help with PHP you can look at:
http://james.jamesandkristin.net/2005/11/18/php-session-cookie-in-frames-using-internet-explorer/#comment-55622
Cheers
/isak
Great suggestion. It works in ASP also: in Global.asa, sub Session_OnStart, just add the following line:
ReplyDeleteResponse.AddHeader "p3p", "CP=""IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"""
HTH
cheers
Luca
Can we solve 'session loss' issue with iframes using hidden variables or URL rewriting?
ReplyDeleteI had the same problem; login worked with Firefox and all other browsers, not with IE.
ReplyDeleteIt didn't work in IE on www.mysite.com but worked in IE on http://mysite.com.mywebfarm.myprovider.com
After days of trying everything, and with a little modification on this HttpModule I finally got it working by redirecting the users to the second domain immediately. Instead of using
...AddHeader("p3p, "CP=...)
I used:
string url = context.Request.RawUrl;
if (url.IndexOf("mywebfarm") < 1)
{
context.Response.Status = "301 Moved Permanently";
context.Response.AddHeader("Location", "http://mysite.com.mywebfarm.myprovider.com");
}
This way my users could still use www.mysite.com but where in fact working on the subdomain without loss of the session/cookies...
This fixed a fairly critical bug. Thanks, Peter Bromberg, and, as always, thanks to Google even though they're taking over the world and they help China sensor information.
ReplyDeleteits not working for me :(
ReplyDeleteI have tried to add
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("p3p", "CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"");
}
in global.asax and reset IIS but it didnt worked for me..any help?