Get Cross-Domain iFrame content - javascript

I would like to know how I can get content from an IFrame cross-domain?
I have no problem getting content from a non-cross-domain iFrame, but when it's located on another domain, JavaScript doesn't allow access.

You use Cross Document Messaging, here's an example. Here's the significant code from the parent page:
window.addEventListener('message', receiver, false);
function receiver(e) {
document.getElementById('message').value = e.data;
}
function update_child() {
var el = document.getElementsByTagName('iframe')[0];
el.contentWindow.postMessage('Updated from parent', '*');
}
The child page has identical code - note that you need to be able to implement the interface on both domains for this to work, either by yourself, if you control both, or in co-operation with the owner of the other domain. In production code you should set (and check) the origin.

Short of requesting it via a proxy on your own server, you can't.
The same origin policy prevents it (and for good reason; I would be very unhappy if you loaded my banking site in your iframe and read all my account details)

Related

Is it possible to send a postMessage to a sandboxed iframe WITHOUT the "allow-scripts" flag?

Basicly I have a cross domain iframe and can't enable the allow-scripts flag, but at the same time I need to get the postMessage that is in a <script> tag in the iframe document OR access the iframe contentDocument.
I've tried:
let iframeElement = document.getElementsByTagName('iframe')[0];
let iframeContent = iframeElement.contentDocument
console.log(iframeContent)
But with the sandbox flag I only get a null return.
What I need to be able to do is one of those three options:
Add a eventListener to a tag that's insde the iframe contentDocument
Get a attr value that's also inside the iframe contentDocument
A way to send a JSON from the origin page and get this JSON in the page with the iframe (postMessage)
But all of this without the allow-scripts flag, is what i'm trying to archieve even possible ?
The simple answer is no.
An <iframe> with its sandbox attribute restricting the use of scripts can not execute scripts. So you won't be able to call postMessage() from this iframe's context, nor will you be able to fire a callback to an event listener.
Now, since your document doesn't satisfies the cross-origin policies, you are stuck, with no way to interact with the <iframe>'s document from outside.
The only workaround, if this feature is a must have, would be to use your server as a proxy so that your iframe's content be actually fetched and served by your own server.
This way, no cross-origin issue anymore (if you add the allow-same-origin policy on your iframe) and you'll be able to access your iframe's content from your parent's doc, or even add event listeners, even though still no scripts could run from this <iframe>'s context, everything would be ran from the main's doc's context. (This means still no postMessage() from the <iframe>).
To quote part of your question,
I need to get the postMessage that is in a <script> tag in the iframe document
If you mean that you need to put or inject a <script> tag which contains postMessaging, then I'm afraid it's not possible because the same-origin policy will prevent it.
If however, you're trying to get access to or listen to a postMessage broadcast from a <script> tag within a cross-origin iframe, then yep, that's exactly what postMessage was designed to achieve. Provided that your message event listener is hosted on the origin as defined in the postMessage's targetOrigin argument.
PostMessage is essentially a contract of trust, to overcome cross-origin barriers; by either having...
access and permission to author the contents of the iframe
been entrusted to listen to broadcasted messages by way of being hosted on the targetOrigin defined (recommended) or by being on any origin if the targetOrigin has a wildcard '*' value (not recommended)
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Security_concerns

How to avoid Uncaught SecurityError: Blocked a frame with origin with phonegap

I am trying to build a phonegap app, which acts as a mini browser for a clients website. The clients customers would open this app, it would have a list of favorites. They could click on one of these favorites and it'd open that favorite within the minibrowser.html page. The minibrowser.html, has a favorites button at the top, then it has an iframe that should act as the browser. I open the favorites by changing the iframes src. I can capture the title/url with this code
$iframe.on('load', () => {
try {
console.log($iframe[0].contentDocument.title);
currentUrl = $iframe[0].contentDocument.URL;
console.log(currentUrl);
} catch (e) {}
});
But the problem occurs when the webpage within the iframe trys to access window.top with this line
window.top.scrollTo(0,1);
That throws the error:
Uncaught SecurityError: Blocked a frame with origin "https://webapp.company.com" from accessing a frame with origin "file://". The frame requesting access has a protocol of "https", the frame being accessed has a protocol of "file". Protocols must match.
Is there anyway to spoof window.top for the iframe? Is there anyway of doing this without hosting the phonegap code on webapp.company.com. I do not have access to webapp.company.com
Due to the nature of the HTTPS protocol, it's mandatory for the server to specify if it's accepting third-party frame distribution (something like what you're trying to do). This is done as it's a major flaw when it comes to security.
Imagine, a person may use a simple variant of this hack to show a part of the Facebook page, and capture your account details. This policy prevents that.
A simple workaround would be to use some sort of URL shortener, or a proxy forwarder.
For a quick example: http://codepen.io/nakshatra334/pen/OMgLLP and open up the console; you'll see the content security policy.
The header, X-Frame-Options is denying this as people may use this for illicit purposes.

javascript iframe: accessing http from https

I have a page that has an iframe which loads html template from amazon aws s3 bucket. In the iframe, I want to take the link of the parent window, then add some parameters.
E.g: My parent window has the link http://xx.xx.x.xxx:8088 . I want to take this url, apprend "#abc/edf" and redirect to that page. But I cannot because my iFrame has url https://bucketName.s3.amazonaws.com
The error I get is
Uncaught SecurityError: Blocked a frame with origin "https://bucketName.s3.amazonaws.com" from accessing a frame with origin "http://xx.xx.x.xxx:8088". The frame requesting access has a protocol of "https", the frame being accessed has a protocol of "http". Protocols must match.
The javascript I used to redirect to another page from within an iFrame
function navigateTo(e){
var destination = e.data.destination;
var url = window.parent.location.host;
window.parent.location.href = url+destination;
}
$("#button").click({destination: "/#abc/edf"}, navigateTo);
html
<div id="button">Redirect to another page</div>
I cannot use absolute path for a reason. The parent window link will change somehow. I think the best solution is to take the parent url and append the parameters that I want. How can I make this happen without getting the security error?
Short answer is "you can't."
Browser security model precludes cross-domain and cross-protocol scripting from the client side. Your embedded iframe under the https protocol is not allowed to access (not even read) its parent's non-https context.
To do what you want, both contexts must agree on both domain of origin and protocol in order to interact on the client side.

regarding alternative option to iframe?

I am doing a project with my client in which I want open multiple website on single page on browser, for this purpose I used iframe but, I was stuck during openerp frame. In iframe I have set openerp screen also, but problem is that when I create a customer as soon as it gets to the creating time, the wizards are not opened.
Some of the code is here:
<iframe src="http://localhost:8069" name="mainFrame" >
I would like to know of an alternative to <iframe>
The ability to access multiple websites, in a browser, via javascript is heavily limited for security reasons. I'm going to call this idea of displaying other webpages via javascript an iframe imitator. For this application, I would set three categories of sites:
Host Site: on the host site, an iframe imitator can be made with a simple ajax request. This is kid's stuff.
1st Party Site (Other than Host): On any site where you have access to server configurations (or at least can modify headers), you will need to specify the header Access-Control-Allow-Origin: "host site name here" to allow the host site's access or Access-Control-Allow-Origin: * to allow every site's access.
3rd Party Site: On third party site's you will have to hope that the site's Access-Control-Allow-Origin header is set to * or else you will need to convince the site's administrators to make an exception and allow your site's access.
If none of the above conditions can be met, then you will be at the mercy of the user's browser security. Some browsers support CORS (Cross Origin Resource Sharing), but it is not dependable. Typically, a user's browser blocks access to certain headers (for security reasons), but if the browser provides support (or has loose enough security), then the headers can be set to trick other sites into giving you access. Be aware that (if allowed) some might consider this borderline hacking, and it probably shouldn't be used without the permission of all parties involved.
$(document).ready(function() {
var target_domain = "www.web-source.net";
var protocol = "http://";
var path = ""; //e.g. "/index.html"
var target_host = protocol + target_domain;
var target_URI = target_host + path;
var method = "GET";
$.ajax({
url: target_URI,
type: method,
headers: {
"X-Requested-With": "", //nullifies the default AJAX value of "XMLHttpRequest"
"Origin": target_host, //lies to the target server
"Referer": target_host, //lies to the target server
"X-Http-Method-Override": method, //forces the specified method
},
crossDomain: "true" //applies cross domain settings
});
});
$(document).ajaxSuccess(function() {
$("#iframe_imitator").html(xhr.responseText);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="iframe_imitator"></div>
I found this in this post - might be worth a try
Alternative to iFrames with HTML5
<object data="http://www.web-source.net" width="600" height="400">
<embed src="http://www.web-source.net" width="600" height="400">
Error: Embedded data could not be displayed.
</object>
I think you can use jQuery load:
<div id="divId"></div>
<script type='text/javascript'>
$(document).ready(function (){
$('#divId').load(URL of target);
});
</script>
You can use Ajax or jQuery as an alternative to iframe. I feel jQuery would be much simpler. You can implement it simply as:
$('#SampleElement').load('YourURL');
Here, SampleElement is the ID of the given element.

document.domain same origin policy not working

Despite of the fact that I have seen many articles (including in stackoverflow) demonstrating up how to bypass javascript's same origin policy assigning document.domain property, its not working. I also read in W3C specs that document.domain property is read-only and not all browsers accept setting it and I think that is the cause I can't get that working!
I have a page (domain d1.y.com.br) and I need to invoke a button in an embedded iframe's page (domain d2.x.com.br). I'm setting the parent document.domain attribute to subdomain 'x.com.br' but I'm still receiving the 'access denied' error message in firebug console.
I have also read about JSONP but its not the case here. I really need to interact with iframe's DOM and not only get data from there (using proxy service).
Does really exist any way to bypass same origin policy to interact with the iframe's DOM ???
The proper way to send data between iframes (especially across domains) is using postMessage(). https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage
That effectively "bypasses" the problem by having the recipient of the message verify that the caller has the correct domain - based on whatever rules it wants.

Categories