Working around X-Frame-Options for iframes
The problem:
One of the first things we noticed after migrating to SharePoint 2013 was that our iframes have stopped working, giving the error:
"Refused to display 'http://contoso/pages/home.aspx' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'."
Quickly we could see that this is in fact a security mechanism to prevent click-jacking and others:
"The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a frame or iframe. Sites can use this to avoid Clickjacking attacks, by ensuring that their content is not embedded into other sites."
Soon we realized that, starting SharePoint 2013, an HTTP Module is adding the header "X-Frame-Options" by default, with the value "SAMEORIGIN".
This is effectively preventing the rendering of pages outside the scope of the current web application.
The (attempted) solution:
So what to do?
At first we though we could fiddle around with the IIS by adding a new header.
But since the old header is still there, we end up getting two header entries.
The (actual) solution(s):
After some more research, we finally found some options:
WSP SOLUTION
Ventigrate has a WSP farm solution in CodePlex that "will prevent SharePoint from trying to inject the header in the first place". It gets the job done, at the cost of having to deploy yet another (Full Trust) solution into the farm
ALLOWFRAMING
Use AllowFraming in a Master Page or specific page/app that we want to enable embedding for. In cases where this actually works, this can potentially be one of the best workarounds.
<WebPartPages:AllowFraming ID="AllowFraming" runat="server" />
URL RULE
Install URL Rewrite in IIS and setup a new rule to remove the header (as proposed here)
LOAD BALANCING SETTINGS
For servers being load-balanced, there is typically an easier way, which is to setup in the configuration of the load balancer that this header should not be used (F5, etc.)
Needless to say, take all this with a grain of salt, and understand what X-Frame-Options actually is, and that removing it can potentially open up your website for malicious intents.
The aftermath:
The header issue is now worked out (hopefully), but we may not exactly be in "the clear" just yet.
In my case I was iframing a SharePoint 2013 page inside a SharePoint 2010 site. So I discovered the hard way that "it's not possible to trigger a different rendering mode in a child iframe in IE9" as mentioned by this StackOverflow post and documented here.
So now I could use iframes, but my SharePoint 2013 frame was rendering not in IE10 but in the same mode as the main site (IE8).
To further extend my problem, the jQuery version being used in the iframed site was v2, which BTW is NOT supported in IE8.
There are many ways around this, like having 2010-mode site collections in 2013 or conditionally loading the necessary jQuery version, but I just wanted to alert for this particularity of IE9+ and iframes.
Takeaways:
Links:
X-Frame-Options,
https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
Discussions,
http://sharepoint.stackexchange.com/questions/56644/how-can-i-configure-x-frame-options-allow-from-on-my-sharepoint-installation
http://sharepoint.stackexchange.com/questions/72987/is-there-a-way-to-disable-x-frame-options-response-header-or-at-least-modify-it
One of the first things we noticed after migrating to SharePoint 2013 was that our iframes have stopped working, giving the error:
"Refused to display 'http://contoso/pages/home.aspx' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'."
Quickly we could see that this is in fact a security mechanism to prevent click-jacking and others:
"The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a frame or iframe. Sites can use this to avoid Clickjacking attacks, by ensuring that their content is not embedded into other sites."
Soon we realized that, starting SharePoint 2013, an HTTP Module is adding the header "X-Frame-Options" by default, with the value "SAMEORIGIN".
This is effectively preventing the rendering of pages outside the scope of the current web application.
The (attempted) solution:
So what to do?
At first we though we could fiddle around with the IIS by adding a new header.
But since the old header is still there, we end up getting two header entries.
The (actual) solution(s):
After some more research, we finally found some options:
WSP SOLUTION
Ventigrate has a WSP farm solution in CodePlex that "will prevent SharePoint from trying to inject the header in the first place". It gets the job done, at the cost of having to deploy yet another (Full Trust) solution into the farm
ALLOWFRAMING
Use AllowFraming in a Master Page or specific page/app that we want to enable embedding for. In cases where this actually works, this can potentially be one of the best workarounds.
<WebPartPages:AllowFraming ID="AllowFraming" runat="server" />
URL RULE
Install URL Rewrite in IIS and setup a new rule to remove the header (as proposed here)
LOAD BALANCING SETTINGS
For servers being load-balanced, there is typically an easier way, which is to setup in the configuration of the load balancer that this header should not be used (F5, etc.)
Needless to say, take all this with a grain of salt, and understand what X-Frame-Options actually is, and that removing it can potentially open up your website for malicious intents.
The aftermath:
The header issue is now worked out (hopefully), but we may not exactly be in "the clear" just yet.
In my case I was iframing a SharePoint 2013 page inside a SharePoint 2010 site. So I discovered the hard way that "it's not possible to trigger a different rendering mode in a child iframe in IE9" as mentioned by this StackOverflow post and documented here.
So now I could use iframes, but my SharePoint 2013 frame was rendering not in IE10 but in the same mode as the main site (IE8).
To further extend my problem, the jQuery version being used in the iframed site was v2, which BTW is NOT supported in IE8.
There are many ways around this, like having 2010-mode site collections in 2013 or conditionally loading the necessary jQuery version, but I just wanted to alert for this particularity of IE9+ and iframes.
Takeaways:
- SharePoint 2013 introduces X-Frame-Options header which will prevent the embedding of iframes to external websites
- Simply adding the header in IIS is not enough of a solution in order to work around this (potentially works outside the SharePoint ecosystem)
- AllowFraming is a great way of supporting iframes on specific pages or sites
- Internet Explorer 9+ now prevents the embedding of an iframe in a different rendering mode than it's parent (in another words, it uses the parent's rending mode)
- jQuery v2 is not supported in IE8 (or any IE version in a page with IE8 rendering mode)
Links:
X-Frame-Options,
https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
Discussions,
http://sharepoint.stackexchange.com/questions/56644/how-can-i-configure-x-frame-options-allow-from-on-my-sharepoint-installation
http://sharepoint.stackexchange.com/questions/72987/is-there-a-way-to-disable-x-frame-options-response-header-or-at-least-modify-it
Comments
Post a Comment