Overcoming "Display forbidden by X-Frame-Options"
Asked Answered
M

26

454

I'm writing a tiny webpage whose purpose is to frame a few other pages, simply to consolidate them into a single browser window for ease of viewing. A few of the pages I'm trying to frame forbid being framed and throw a "Refused to display document because display forbidden by X-Frame-Options." error in Chrome. I understand that this is a security limitation (for good reason), and don't have access to change it.

Is there any alternative framing or non-framing method to display pages within a single window that won't get tripped up by the X-Frame-Options header?

Miticide answered 12/7, 2011 at 15:6 Comment(11)
If they're your pages, then remove the frame limiter. Otherwise, respect the page's author's wishes and DON'T FRAME THEM.Wrap
If you are getting this error for a Facebook App and using AJAX calls, i read somewhere that Facebook really likes using # tags for it's ajax contact so try changing links, worked for me.Solenne
Make sure you enable the google maps embed api in addition to places API. Generate you map from here: developers.google.com/maps/documentation/embed/startObliteration
Also make sure to have 3rd party cookies enabled in your browser. Took me several hours to figure it out, and it solved my problem.Orelia
@MarcB Chrome and Firefox ethically frame non-owned websites in native UI chrome. These programs also allow relaxed same-origin policies to their owners, FWIW. As garen-checkly said, "I'm writing a tiny webpage whose purpose is to frame a few other pages, simply to consolidate them into a single browser window for ease of viewing." That's basically extending the web-browser and would be completely ethical. The stated intent is no different from writing a bash script to open and arrange browser windows.Debris
Check Surfly. It can do exactly what you need.Dilworth
Surfly looks nice, but for 20 EUR/month... I think I'll just open another browser window. ;)Sainted
Whatever possible the trik on server side is consider as a bug. It has to be aware that for Chrome (and all webkit-based browsers) sooner or later they will no longer support for XFrame-Options: Allow-From statements at all. So it just a matter of time, Unless you able to find an alternative way like Content-Security-Policy, I would suggest to change the method of displaying an external content in iframe in to an acceptable one.Smooth
@MarcB That's not helpful. OP might not care about the page author's wishes.Palpitation
@Chetabahana An Acceptable one? What other alternatives would you suggest?Overdrive
@legit-stack Any alternatives that other than frame the external content. For instance use a web proxy, or fetching the content and rewrite it in to a block in pages.Smooth
H
221

If a website refuses to be framed, there is no way to overcome that.

(This post previously contained incorrect advice suggesting adding another X-Frame-Options header whose value is GOFORIT, but in all implementations that would also result in the website refusing to be framed and didn't actually address the question from OP.)

Hexangular answered 20/7, 2011 at 20:13 Comment(8)
I had a frame around a website. On my website, I'm redirecting to Instagram for OAUTH. Since Instagram sends X-Frame-Options: SAMEORIGIN there is no way to do this inside the frame. You must use a popup.Trigeminal
With PHP it's probably better to use the new header_remove function, provided you have it available (>=5.3.0).Retain
Or you can edit .htaccess if you want to remove X-Frame-Options from an entire directory. Just add the line: Header always unset X-Frame-OptionsNicolnicola
I did it and got another error now: Invalid 'X-Frame-Options' header encountered when loading 'domain.com': 'GOFORIT' is not a recognized directive. The header will be ignored.Caddish
@cawecoy: Well yes, the whole point is that it's invalid. It relies on browsers ignoring the invalid header and ‘failing open’, which is unspecified behaviour and pretty dodgy to rely on. GOFORIT (or other random arbitrary invalid token) is deliberately breaking a security measure applied by a server; if you have control of the server yourself (which you should do for any real public service) then the correct thing to do is just set the server not to set the header in the first place.Portuna
This doesn't seem to work any longer in Chrome. Invalid values cause the value to default to DENY.Abseil
Header always unset X-Frame-Options doesn't work. Apache throws a 500.Lorri
Remove the X-Frame-Options header from the page referenced in iframe src="...". For Rails, see #18446282Carlicarlick
B
165

If you are getting this error for a YouTube video, rather than using the full url use the embed url from the share options. It will look like http://www.youtube.com/embed/eCfDxZxTBW4

You may also replace watch?v= with embed/ so http://www.youtube.com/watch?v=eCfDxZxTBW4 becomes http://www.youtube.com/embed/eCfDxZxTBW4

Bestraddle answered 15/12, 2011 at 14:1 Comment(1)
Oh progress... I wish they would just redirect us to the embed page instead of causing an error to be thrown, and making me rewrite my scripts!Ocker
P
120

If you are getting this error while trying to embed a Google Map in an iframe, you need to add &output=embed to the source link.

Processional answered 19/9, 2011 at 11:9 Comment(10)
That is only true for embedding google maps in an iframe, and not a general "solution".Arrington
I needed to embed a google map in a lightbox, so this "solution" was perfectLoudish
If you're trying to do this with a Twitter web intent, forget about it. Just lost all day trying different lightbox plugins only to find out this "While you can provide links to intents within IFRAMEs and widgets, the resultant pages cannot be loaded in an IFRAME." Source: Twitter website.Tva
@QLStudio What's the whole point of disabling it in the first place, only to allow it with a different url? I mean click-jackers could simply attach &output=embed no?Trichiasis
@Trichiasis Assumably, the view would change to one deemed embeddable.Tervalent
This does not work if you are trying to load the iframe src after the rest of the page loads even if you add &output=embedSiddons
@Q Studio thanks a lot, worked like a charm for me while loading a Freebase page into iframe.Blindworm
@Siddons This worked for me when I had trouble loading the iframe src after the page had loadedTong
This doesn't work for links beginning mapsengine.google.com - e.g. mapsengine.google.com/map/… . Any idea how to make those work?Kweiyang
As of Summer 2014 Youtube doesn't do things this way anymore, making this answer incorrectAnnounce
O
80

UPDATE 2019: You can bypass X-Frame-Options in an <iframe> using just client-side JavaScript and my X-Frame-Bypass Web Component. Here is a demo: Hacker News in an X-Frame-Bypass. (Tested in Chrome & Firefox.)

Olav answered 30/8, 2014 at 23:5 Comment(12)
That's an interesting workaround. Works well in FF/Chrome/Opera but doesn't work in IE/Edge though. Anyone who knows something which will?Refreshing
This does not work anymore. It gives "Refused to display 'news.ycombinator.com' in a frame because it set 'X-Frame-Options' to 'DENY'." as expectedDoge
@Doge It works for me in Google Chrome 46, I can see Hacker News in an iframe.Olav
worked intermittently for me and some Chrome 48. Sometimes I get Refused to display 'news.ycombinator.com' in a frame because it set 'X-Frame-Options' to 'DENY'.Scaler
Ok for Chrome 50 and FF 46.0.1. Nothing for IE sadly (ofc, the only one I needed it to work with)Signora
@mark There was a problem with mixed content, try the updated fiddle.Olav
@Olav that fiddle works after reloading the page in Chrome 64, but the first time I load the page it doesn't work. (Try in incognito.)Ebon
That is strange... same as @CarlWalsh, in chrome 64, fails on first load (same error as @g.pickardou), but I opened a second time and it now works... Can you explain how this works?Parent
How come this is not fixed in all major browsers yet? For me, it works with Firefox 61 against both X-Frame-Options: sameorigin and X-Frame-Options: deny.Caitiff
@CarlWalsh try invoking window.reload() on page load, maybe it will help?Olav
Since YQL is no longer available, I've updated the answer.Olav
Wow, thanks so much for the workaround. It worked on nearly all the URLs I tried, but a couple of them produced errors. One URL, which worked the normal iframe way, produced a "srcdoc" error with X-Frame-Bypass, but worked later when I tried again. The other URL, which did not work in my old code, produced a "Application rendering error" and a reload button that didn't seem to do anything.Standley
F
22

Adding a

  target='_top'

to my link in the facebook tab fixed the issue for me...

Fiorenze answered 24/8, 2012 at 11:40 Comment(2)
I had the same issue with the Paypal iframe contained in another iframe. It works now! ThanksHeliotrope
I also added target='_top', but problem with this solution is , the link now opens outside the iframe in new tab without facebook canvas.Ebersole
G
21

If you're getting this error trying to embed Vimeo content, change the src of the iframe,

from: https://vimeo.com/63534746
to: http://player.vimeo.com/video/63534746

Grave answered 31/5, 2013 at 16:26 Comment(1)
this solved my problem, thankyou. what to do with youtube videos??Philadelphia
S
14

I had same issue when I tried embed moodle 2 in iframe, solution is Site administration ► Security ► HTTP security and check Allow frame embedding

Supergalaxy answered 16/4, 2012 at 12:28 Comment(1)
well done for the moodle method, since the other methods fail/get overwritten.Hellbender
A
8

I tried nearly all suggestions. However, the only thing that really solved the issue was:

  1. Create an .htaccess in the same folder where your PHP file lies.

  2. Add this line to the htaccess:

    Header always unset X-Frame-Options

Embedding the PHP by an iframe from another domain should work afterwards.

Additionally you could add in the beginning of your PHP file:

header('X-Frame-Options: ALLOW');

Which was, however, not necessary in my case.

Archpriest answered 2/9, 2016 at 18:48 Comment(0)
R
8

Solution for loading an external website into an iFrame even tough the x-frame option is set to deny on the external website.

If you want to load a other website into an iFrame and you get the Display forbidden by X-Frame-Options” error then you can actually overcome this by creating a server side proxy script.

The src attribute of the iFrame could have an url looking like this: /proxy.php?url=https://www.example.com/page&key=somekey

Then proxy.php would look something like:

if (isValidRequest()) {
   echo file_get_contents($_GET['url']);
}

function isValidRequest() {
    return $_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['key']) && 
    $_GET['key'] === 'somekey';
}

This by passes the block, because it is just a GET request that might as wel have been a ordinary browser page visit.

Be aware: You might want to improve the security in this script. Because hackers could start loading in webpages via your proxy script.

Rodd answered 20/2, 2018 at 9:50 Comment(4)
I was doing this a few weeks ago and any relative URLs used in the external page do not function when using echo. (Typically CSS and/or JS, so you might not get full functionality unless you modify URLs before echoing.) Unless I've missed something...,Standley
Not sure why this happens for you... It should work like a normal HTTP request, just like an end-user would perform when visiting the URL. So the result of the get_file_contents() should be a completely working HTML page.Rodd
Well I may have been missing something in code, but wouldn't a straight echo would be serving up the HTML markup from "your" domain, not the source domain? So relative links would not function correctly. A proper proxy is probably not what I had. I'll try your code.Standley
How can I implement the same proxy in JavaScript?Presbyter
T
7

This is the solution guys!!

FB.Event.subscribe('edge.create', function(response) {
    window.top.location.href = 'url';
});

The only thing that worked for facebook apps!

Tetroxide answered 21/1, 2013 at 14:16 Comment(0)
B
7

It appears that X-Frame-Options Allow-From https://... is depreciated and was replaced (and gets ignored) if you use Content-Security-Policy header instead.

Here is the full reference: https://content-security-policy.com/

Banda answered 14/6, 2017 at 12:25 Comment(0)
I
4

I had the same problem with mediawiki, this was because the server denied embedding the page into an iframe for security reasons.

I solved it writing

$wgEditPageFrameOptions = "SAMEORIGIN"; 

into the mediawiki php config file.

Hope it helps.

Indole answered 9/3, 2013 at 23:1 Comment(0)
M
3

FWIW:

We had a situation where we needed to kill our iFrame when this "breaker" code showed up. So, I used the PHP function get_headers($url); to check out the remote URL before showing it in an iFrame. For better performance, I cached the results to a file so I was not making a HTTP connection each time.

Metempsychosis answered 19/3, 2012 at 3:43 Comment(0)
O
3

Not mentioned but can help in some instances:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
    if (xhr.readyState !== 4) return;
    if (xhr.status === 200) {
        var doc = iframe.contentWindow.document;
        doc.open();
        doc.write(xhr.responseText);
        doc.close();
    }
}
xhr.open('GET', url, true);
xhr.send(null);
Obstinate answered 19/3, 2014 at 6:22 Comment(0)
B
3

I was using Tomcat 8.0.30, none of the suggestions worked for me. As we are looking to update the X-Frame-Options and set it to ALLOW, here is how I configured to allow embed iframes:

  • Navigate to Tomcat conf directory, edit the web.xml file
  • Add the below filter:
<filter>
            <filter-name>httpHeaderSecurity</filter-name>
            <filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
                   <init-param>
                           <param-name>hstsEnabled</param-name>
                           <param-value>true</param-value>
                   </init-param>
                   <init-param>
                           <param-name>antiClickJackingEnabled</param-name>
                           <param-value>true</param-value>
                   </init-param>
                   <init-param>
                           <param-name>antiClickJackingOption</param-name>
                           <param-value>ALLOW-FROM</param-value>
                   </init-param>
            <async-supported>true</async-supported>
       </filter>

       <filter-mapping>
                   <filter-name>httpHeaderSecurity</filter-name>
                   <url-pattern>/*</url-pattern>
                   <dispatcher>REQUEST</dispatcher>
       </filter-mapping> 
  • Restart Tomcat service
  • Access the resources using an iFrame.
Burdette answered 8/12, 2016 at 16:34 Comment(0)
P
3

The only real answer, if you don't control the headers on your source you want in your iframe, is to proxy it. Have a server act as a client, receive the source, strip the problematic headers, add CORS if needed, and then ping your own server.

There is one other answer explaining how to write such a proxy. It isn't difficult, but I was sure someone had to have done this before. It was just difficult to find it, for some reason.

I finally did find some sources:

https://github.com/Rob--W/cors-anywhere/#documentation

^ preferred. If you need rare usage, I think you can just use his heroku app. Otherwise, it's code to run it yourself on your own server. Note sure what the limits are.

whateverorigin.org

^ second choice, but quite old. supposedly newer choice in python: https://github.com/Eiledon/alloworigin

then there's the third choice:

http://anyorigin.com/

Which seems to allow a little free usage, but will put you on a public shame list if you don't pay and use some unspecified amount, which you can only be removed from if you pay the fee...

Parent answered 26/4, 2018 at 22:26 Comment(0)
S
2

The only question that has a bunch of answers. WElcome to the guide i wish i had when i was scrambling for this to make it work at 10:30 at night on the deadline day... FB does some weird things with canvas apps, and well, you've been warned. If youa re still here and you have a Rails app that will appear behind a Facebook Canvas, then you will need:

Gemfile:

gem "rack-facebook-signed-request", :git => 'git://github.com/cmer/rack-facebook-signed-request.git'

config/facebook.yml

facebook:
  key: "123123123123"
  secret: "123123123123123123secret12312"

config/application.rb

config.middleware.use Rack::Facebook::SignedRequest, app_id: "123123123123", secret: "123123123123123123secret12312", inject_facebook: false

config/initializers/omniauth.rb

OmniAuth.config.logger = Rails.logger
SERVICES = YAML.load(File.open("#{::Rails.root}/config/oauth.yml").read)
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :facebook, SERVICES['facebook']['key'], SERVICES['facebook']['secret'], iframe:   true
end

application_controller.rb

before_filter :add_xframe
def add_xframe
  headers['X-Frame-Options'] = 'GOFORIT'
end

You need a controller to call from Facebook's canvas settings, i used /canvas/ and made the route go the main SiteController for this app:


class SiteController < ApplicationController
  def index
    @user = User.new
  end
  def canvas
    redirect_to '/auth/failure' if request.params['error'] == 'access_denied'
    url = params['code'] ? "/auth/facebook?signed_request=#{params['signed_request']}&state=canvas" : "/login"
    redirect_to url
  end
  def login
  end
end

login.html.erb


<% content_for :javascript do %>
  var oauth_url = 'https://www.facebook.com/dialog/oauth/';
  oauth_url += '?client_id=471466299609256';
  oauth_url += '&redirect_uri=' + encodeURIComponent('https://apps.facebook.com/wellbeingtracker/');
  oauth_url += '&scope=email,status_update,publish_stream';
console.log(oauth_url);
  top.location.href = oauth_url;
<% end %>

Sources

  • The config i think came from omniauth's example.
  • The gem file (which is key!!!) came from: slideshare things i learned...
  • This stack question had the whole Xframe angle, so you'll get a blank space, if you don't put this header in the app controller.
  • And my man @rafmagana wrote this heroku guide, which now you can adopt for rails with this answer and the shoulders of giants in which you walk with.
Segno answered 3/8, 2013 at 2:12 Comment(0)
F
2
<form target="_parent" ... />

Using Kevin Vella's idea, I tried using the above on the form element made by PayPal's button generator. Worked for me so that Paypal does not open in a new browser window/tab.

Update

Here's an example:

Generating a button as of today (01-19-2021), PayPal automatically includes target="_top" on the form element, but if that doesn't work for your context, try a different target value. I suggest _parent -- at least that worked when I was using this PayPal button.

See Form Target Values for more info.

<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_parent">
  <input type="hidden" name="cmd" value="_xclick">
  <input type="hidden" name="business" value="[email protected]">
  <input type="hidden" name="lc" value="US">
  <input type="hidden" name="button_subtype" value="services">
  <input type="hidden" name="no_note" value="0">
  <input type="hidden" name="currency_code" value="USD">
  <input type="hidden" name="bn" value="PP-BuyNowBF:btn_buynowCC_LG.gif:NonHostedGuest">
  <input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
  <img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
Forcible answered 21/2, 2014 at 18:22 Comment(2)
Unfortunately this does not seem to work for safari too.Recumbent
@Forcible can you please provide an example too?Dispenser
F
2

Site owners use the X-Frame-Options response header so that their website cannot be opened in an Iframe. This helps to secure the users against clickjacking attack

There are a couple of approaches that you can try if you want to disable X-Frame-Options on your own machine.

Configuration at Server-Side

If you own the server or can work with the site owner then you can ask to set up a configuration to not send the Iframe buster response headers based on certain conditions. Conditions could be an additional request header or a parameter in the URL.

For example - The site owner can add an additional code to not send Iframe buster headers when the site is opened with ?in_debug_mode=true query param.

Use Browser extension like Requestly to remove response headers

You can use any browser extension like Requestly which allows you to modify the request & response headers. Here's a Requestly blog that explains how to embed sites in Iframe by bypassing Iframe buster headers.

enter image description here

Configure a Pass-through Proxy and remove headers from it

If you need to bypass Iframe buster headers for multiple folks, then you can also configure a pass-through proxy that just removes the frame buster response headers and return back the response. This is however a lot complicated to write, set up. There are some other challenges like authentication etc with the sites opened in Iframe through a proxy but this approach can work for simple sites pretty well.

PS - I have built both solutions and have first-hand experience with both.

Fernandafernande answered 31/1, 2022 at 10:8 Comment(0)
A
1

I'm not sure how relevant it is, but I built a work-around to this. On my site, I wanted to display link in a modal window that contained an iframe which loads the URL.

What I did is, I linked the click event of the link to this javascript function. All this does is make a request to a PHP file that checks the URL headers for X-FRAME-Options before deciding whether to load the URL within the modal window or to redirect.

Here's the function:

  function opentheater(link, title){
        $.get( "url_origin_helper.php?url="+encodeURIComponent(link), function( data ) {
  if(data == "ya"){
      $(".modal-title").html("<h3 style='color:480060;'>"+title+"&nbsp;&nbsp;&nbsp;<small>"+link+"</small></h3>");
        $("#linkcontent").attr("src", link);
        $("#myModal").modal("show");
  }
  else{
      window.location.href = link;
      //alert(data);
  }
});


        }

Here's the PHP file code that checks for it:

<?php
$url = rawurldecode($_REQUEST['url']);
$header = get_headers($url, 1);
if(array_key_exists("X-Frame-Options", $header)){
    echo "nein";
}
else{
    echo "ya";
}


?>

Hope this helps.

Agleam answered 19/12, 2013 at 11:1 Comment(0)
A
1

I came across this issue when running a wordpress web site. I tried all sorts of things to fix it and wasn't sure how, ultimately the issue was because I was using DNS forwarding with masking, and the links to external sites were not being addressed properly. i.e. my site was hosted at http://123.456.789/index.html but was masked to run at http://somewebSite.com/index.html. When i entered http://123.456.789/index.html in the browser clicking on those same links resulted in no X-frame-origins issues in the JS console, but running http://somewebSite.com/index.html did. In order to properly mask you must add your host's DNS name servers to your domain service, i.e. godaddy.com should have name servers of example, ns1.digitalocean.com, ns2.digitalocean.com, ns3.digitalocean.com, if you were using digitalocean.com as your hosting service.

Affirmatory answered 3/6, 2014 at 0:2 Comment(1)
I ended up doing: remove_action( 'admin_init', 'send_frame_options_header',10); to bypass this problem...Kinghorn
W
1

It's surprising that no one here has ever mentioned Apache server's settings (*.conf files) or .htaccess file itself as being a cause of this error. Search through your .htaccess or Apache configuration files, making sure that you don't have the following set to DENY:

Header always set X-Frame-Options DENY

Changing it to SAMEORIGIN, makes things work as expected:

Header always set X-Frame-Options SAMEORIGIN

Watters answered 5/8, 2015 at 11:14 Comment(4)
it was mentioned before - see the comment from @Nicolnicola on the answer https://mcmap.net/q/75122/-overcoming-quot-display-forbidden-by-x-frame-options-quotCassaundra
I config .conf file Header always set X-Frame-Options SAMEORIGIN!Ozonide
But how is this relevant to the question here, where the header comes from foreign servers, directly to the client, IOW your own server is not even involved? Am I missing something?Sainted
@iliarostovtsev the .htaccess option doesn't work.Dispenser
Q
1

i had this problem, and resolved it editing httd.conf

<IfModule headers_module>
    <IfVersion >= 2.4.7 >
        Header always setifempty X-Frame-Options GOFORIT
    </IfVersion>
    <IfVersion < 2.4.7 >
        Header always merge X-Frame-Options GOFORIT
    </IfVersion>
</IfModule>

i changed SAMEORIGIN to GOFORIT and restarted server

Queeniequeenly answered 11/8, 2015 at 13:58 Comment(0)
L
0

Edit .htaccess if you want to remove X-Frame-Options from an entire directory.

And add the line: Header always unset X-Frame-Options

[contents from: Overcoming "Display forbidden by X-Frame-Options"

Lemar answered 16/7, 2019 at 13:12 Comment(0)
U
-1

Use this line given below instead of header() function.

echo "<script>window.top.location = 'https://apps.facebook.com/yourappnamespace/';</script>";
Unsaddle answered 7/10, 2013 at 10:54 Comment(0)
U
-2

Try this thing, i dont think anyone suggested this in the Topic, this will resolve like 70% of your issue, for some other pages, you have to scrap, i have the full solution but not for public,

ADD below to your iframe

sandbox="allow-same-origin allow-scripts allow-popups allow-forms"

Uncover answered 2/10, 2017 at 7:59 Comment(1)
sandboxing reduces privileges, it doesn't add them. see html5rocks.com/en/tutorials/security/sandboxed-iframesParent

© 2022 - 2024 — McMap. All rights reserved.