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:


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.

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.