How can I set 'X-Frame-Options' on an iframe?
Asked Answered
C

15

241

If I create an iframe like this:

var dialog = $('<div id="' + dialogId + '" align="center"><iframe id="' + frameId + '" src="' + url + '" width="100%" frameborder="0" height="'+frameHeightForIe8+'" data-ssotoken="' + token + '"></iframe></div>').dialog({

How can I fix the following error with JavaScript?

Refused to display 'https://www.google.com.ua/?gws_rd=ssl' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.

Coppinger answered 8/12, 2014 at 13:20 Comment(0)
E
300

You can't set X-Frame-Options on the iframe. That is a response header set by the domain from which you are requesting the resource (google.com.ua in your example). They have set the header to SAMEORIGIN in this case, which means that they have disallowed loading of the resource in an iframe outside of their domain. For more information see The X-Frame-Options response header on MDN.

A quick inspection of the headers (shown here in Chrome developer tools) reveals the X-Frame-Options value returned from the host.

enter image description here

Examine answered 8/12, 2014 at 13:23 Comment(3)
With YouTube, you can change the endpoint URL to the "embed" version. See #25661682 (I know this isn't strictly what the OP is searching for, but google gives this result first!)Fanchon
Now 2021. According to the [developer.mozilla.org/en-US/docs/Web/HTTP/Headers/… MDN docs), DENY and SAMEORIGIN are the only remaining valid options, with ALLOW-FROM deemed obsolete. Does this mean that cross-site iframes are officially something of the past (except if explicitly circumvented with plugins, etc.)?Ljoka
Note: The Content-Security-Policy HTTP header has a frame-ancestors directive which obsoletes this header for supporting browsers. Source: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/… Solution: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…Monoatomic
I
104

X-Frame-Options is a header included in the response to the request to state if the domain requested will allow itself to be displayed within a frame. It has nothing to do with javascript or HTML, and cannot be changed by the originator of the request.

This website has set this header to disallow it to be displayed in an iframe. There is nothing that can be done in a client-side web browser to stop this behaviour.

Further reading on X-Frame-Options

Infidelity answered 8/12, 2014 at 13:24 Comment(5)
It's set in the response header, not request header. But otherwise accurate explanation!Noach
@Noach that's what I meant, however I agree the terminology wasn't clear. I've edited it to remove any confusion. Thanks.Infidelity
"There is nothing a client can do to stop this behaviour." - Thank you for clarifying this!Louvre
"There is nothing a client can do to stop this behavior." That's actually not true as my "client" could be a node server (or any other server) that downloads the content of the page (scraping) and makes the content (including CSS, JS, etc) available to be loaded in your own siteLavettelavigne
@Lavettelavigne you're correct. Unfortunately someone edited 'client' in to my answer to create that issue. I've updated the answer to remove that ambiguity.Infidelity
C
46

In case you are in control of the server that sends the content of the iframe, you can set the setting for X-Frame-Options in your web server.

Configuring Apache

To send the X-Frame-Options header for all pages, add this to your site's configuration:

Header always append X-Frame-Options SAMEORIGIN

Configuring nginx

To configure nginx to send the X-Frame-Options header, add this either to your http, server or location configuration:

add_header X-Frame-Options SAMEORIGIN;

No configuration

This header option is optional, so if the option is not set at all, you will give the option to configure this to the next instance (e.g., the visitors browser or a proxy)

Source: X-Frame-Options

Corrales answered 4/3, 2016 at 7:37 Comment(4)
This helped me. I comment out these two lines: add_header Strict-Transport-Security "max-age=86400; includeSubdomains"; add_header X-Frame-Options DENY; from the nginx-snippets, and then it worked straight away.Rabbet
NGINX, important to say where, inside location?Euchre
May I know the location where I need to set this header for Apache?Deemphasize
For Apache add the options inside the <directive> tag for your website, most probably a config file inside /etc/apache2/sites-enabled/Corrales
K
23

Since the solution wasn't really mentioned for the server side:

One has to set things like this (example from Apache). This isn't the best option as it allows in everything, but after you see your server working correctly, you can easily change the settings.

Header set Access-Control-Allow-Origin "*"
Header set X-Frame-Options "allow-from *"
Kaleidoscopic answered 28/11, 2018 at 19:43 Comment(4)
where i need to add this lines ? in proxy ?Passion
@YaaKouB I am not sure what you are trying to do but it can go into the .htaccess or the config files for apache for example. FYI tecadmin.net/configure-x-frame-options-apacheKaleidoscopic
@MikeQ have tried this but getting an issue apache2.service failed because the control process exitedHeffner
allow-from is deprecated you have to remove the header to "allow" embedding. Header always unset X-Frame-OptionsPunnet
M
7

And if nothing helps and you still want to present that website in an iframe, consider using X Frame Bypass Component which will use a proxy.

Murine answered 26/6, 2019 at 11:49 Comment(0)
E
5

Not really... I used:

<system.webServer>
    <httpProtocol allowKeepAlive="true" >
        <customHeaders>
            <add name="X-Frame-Options" value="*" />
        </customHeaders>
    </httpProtocol>
</system.webServer>
Epidaurus answered 7/2, 2018 at 12:40 Comment(3)
This looks like a solution, but is this a security breach?Staten
It's not a good idea to disable same origin policy for your site unless you know exactly what you are doing. You should not allow domains different from yours to embed content. See codecademy.com/articles/what-is-cors and similar tutorials.Psychosurgery
Is it for IIS?Valrievalry
A
4

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>, <iframe> or <object>. Sites can use this to avoid clickjacking attacks, by ensuring that their content is not embedded into other sites.

For more information: X-Frame-Options

I have an alternate solution for this problem, which I am going to demonstrate by using PHP:

File iframe.php

<iframe src="target_url.php" width="925" height="2400" frameborder="0" ></iframe>

File target_url.php

<?php
  echo file_get_contents("http://www.example.com");
?>
Anemic answered 25/10, 2016 at 11:30 Comment(1)
Is this a viable solution to use the page after it loads? Will I be able to interact with the pages after inital load? Wouldn't every request for the domain have to be proxied in order to use the content after it loads?Dioptase
D
3

If you don't have access to the website hosting the web page you want to serve within the <iframe> element, you can circumvent the X-Frame-Options SAMEORIGIN restrictions by using a CORS-enabled reverse proxy that could request the web page(s) from the web server (upstream) and serve them to the end user.

Here's a visual diagram of the concept:

Enter image description here

Since I was unhappy with the CORS proxies I found, I ended up creating one myself, which I called CORSflare: it has been designed to run in a Cloudflare Worker (serverless computing), and therefore it's a 100% free workaround, as long as you don't need it to accept more than 100.000 request per day.

You can find the proxy source code on GitHub; the full documentation, including the installation instruction, can be found in this post of my blog.

Dickey answered 23/7, 2020 at 3:9 Comment(1)
Is Server A requesting the content from Server B, or is the NOdeJS proxy doing that? For instance, is the request IP passed onto the Server B API?Emolument
E
2

This is also a new browser security feature to prevent phishing and other security threats. For chrome, you can download an extension to prevent the browser from denying the request. I encountered this issue while working on WordPress locally.

I use this extension https://chrome.google.com/webstore/detail/ignore-x-frame-headers/gleekbfjekiniecknbkamfmkohkpodhe

Eardrum answered 21/9, 2020 at 23:35 Comment(0)
C
0

For this purpose, you need to match the location in your Apache installation or any other service you are using.

If you are using Apache, then in the httpd.conf file:

<LocationMatch "/your_relative_path">
    ProxyPass absolute_path_of_your_application/your_relative_path
    ProxyPassReverse absolute_path_of_your_application/your_relative_path
</LocationMatch>
Careless answered 18/11, 2015 at 10:51 Comment(0)
R
0

The solution is to install a browser plugin.

A web site which issues HTTP Header X-Frame-Options with a value of DENY (or SAMEORIGIN with a different server origin) cannot be integrated into an IFRAME... unless you change this behavior by installing a Browser plugin which ignores the X-Frame-Options Header (e.g. Chrome's Ignore X-Frame Headers).

Note that this not recommended at all for security reasons.

Regime answered 3/5, 2017 at 21:26 Comment(2)
"solution" is a strong word, I'd say work aroundSlinkman
We can not say every customer to install that plugin to see what's there in our iframe!Emmery
O
0

The way around this is to grab the HTML server side, add a <base href="..." /> so any relative and absolute paths still work.

Here's my node route /api/url/:url

export default async function handler(req, res) {
  const url = `https://${req.query.url}`;
  const response = await fetch(url);
  const urlContents = await response.text();

  // Prepend the base to make sure all relative and absolute paths work
  const urlContentsWithHead = `<base href='${url}' /></head>${urlContents}`;

  res.status(200).send(urlContentsWithHead);
}

You can then use this route directly in the iframe

<iframe src={`/api/url/${url}`} />

Oddly when I tried to do this "properly" by putting the <base /> element just before the closing </head> tag by using a replace, it didn't work. But putting the base before all of the markup (even the <html>) seemed to work.

Not sure if there will be any adverse affects 🤷

Omniscience answered 1/12, 2022 at 12:6 Comment(0)
M
0

You can set it to an invalid value. In PHP

header("X-Frame-Options: ALLOWALL");

this will default to X-Frame-Options not set

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options

Mcelroy answered 27/2 at 15:42 Comment(0)
L
-2

You can not really add the x-iframe in your HTML body as it has to be provided by the site owner and it lies within the server rules.

You can probably create a PHP file which loads the content of the target URL and iframe that php URL. This should work smoothly.

Liverwurst answered 25/3, 2019 at 11:50 Comment(6)
"You can probably" then post it as a comment if its not an answerVashtivashtia
What if it turns out to be an answer MKLiverwurst
Then it is a suggestion that worked, not a specific solution, so it should be placed as a commentVashtivashtia
It seems incomprehensible near "that php URL". Can you fix it? But *** *** *** *** *** without *** *** *** *** *** "Edit:", "Update:", or similar - the answer should appear as if it was written todayValrievalry
OK, the OP has left the building: "Last seen more than 1 year ago"Valrievalry
@PeterMortensen Help me click that delete link.Cassicassia
R
-3

You can do it in the Tomcat instance level configuration file (web.xml). You need to add the 'filter' and filter-mapping' in the web.xml config file. This will add the [X-frame-options = DENY] to all the pages as it is a global setting.

<filter>
    <filter-name>httpHeaderSecurity</filter-name>
    <filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
    <async-supported>true</async-supported>
    <init-param>
        <param-name>antiClickJackingEnabled</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>antiClickJackingOption</param-name>
        <param-value>DENY</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>httpHeaderSecurity</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
Redroot answered 30/5, 2019 at 14:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.