How to overcome same-origin-policy from iframe? - javascript

I'm basically trying to display a second website, belonging to the same organization but hosted on a different domain name, in an Iframe. And I'm trying to pass in some data from the iframe to the parent frame.
Parent frame = foo.com,
Iframe = bar.com
If I try to pass in the data from the iframe via parent.setData( data ), that gives me a same-origin policy error.
So I made a wrapper around this code, hosted at foo.com/js/wrapper.js, which contains this function:
var Foo = {};
Foo.setData = function(data)
{
parent.setData(data);
}
So now my Iframe on bar.com is doing:
<script src="http://foo.com/js/wrapper.js"></script>
<script>
Foo.setData( someData );
</script>
However, even that is giving me a security error on the parent.setData line, even through wrapper.js is hosted on the parent domain.
Is there any other way to overcome this?

You are looking for postMessage, read up on that here: https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage
Edit: sorry, didn't see all of the comments saying the same thing

Another fun way to get around this policy is to hijack the child window.location.hash, as it is also visible to both scripting engines.

Related

How to manipulate cross domain iframe with javascript / JQuery [duplicate]

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)

Access a button inside the IFrame

I am looking for a way to access a button inside the iFrame and trigger a click event when that button is clicked inside the iFrame that is on another domain.
Trying to go deeper into an element within the iFrame has proven difficult. Has anyone had success taking it this far?
Use an ajax call to the iframe's src to get its content, and render it as part of your site (which you then can hook).
You can't access the contents from an iframe from a different domain directly because that would be a security violation.
If i understand your requirements correctly
You can add a $('#iframe').load(function(){} which will watch the loading of iframe into your DOM.
After loading iframe you can attach an event listener to button click
var iframe = $('#iframe').contents();
iframe.find("#button").click(function(){
//write code to close the popup
});
The above process can be summarized as follows
$('#iframe').load(function(){
var iframe = $('#iframe').contents();
iframe.find("#button").click(function(){
$('#popup').close() //May depend on your popup implementation
});
});
The Problem here is that the same-origin policy blocks scripts from accessing contents of site with other origin.
Actually origin consists of the following parts.
origin:<protocol(http/https)>://<hostname>:<port number>/path/to/page.html
The origin is considered to be different if protocol,host name and port number are not same.
In such cases you can not access the contents of one website from other website due to same-origin security policy.
In order to overcome it you have to use parent-child communication using window.postMessage().
FYI : https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage.
The Window.postMessage() method safely enables cross-origin communication.
Suppose that your parent website is example-parent.com and In Iframe your loading website example-iframe.com and let both are using http protocol. Below is how I solved the problem.
In parent website add event listener for messages to receive as follows.
window.addEventListener('message',receiveMessage,false);
function receiveMessage(event){
var origin = event.origin || event.originalEvent.origin;
if(origin.indexOf('http://example-iframe.com')>=0) // check if message received from intended sender
{
if(event.data=="intended message format") // check if data received is in correct format
{
// call functionality that closes popup containing iframe
}else{ // data received is malacious
return;
}
}else{ // message is not received from intended sender
return;
}
}
From Iframe post message to the parent website as follows.
Post message syntax : otherWindow.postMessage(message, targetOrigin, [transfer]);
function sendMessage(){
parent.postMessage('intended message format','http://example-parent.com');
}
Use postMessage() properly,otherwise it may lead to cross-site scripting attack.
I am Sorry to say this to you but, you can't.
Since that will be violating CORS (Cross-origin resource sharing) rules that browser has set and it won't let you break those. Since its the almighty.
It will give an error 'Access-Control-Allow-Origin' in your console .
Hope you find it helpful.
Still if want to do something in your website you can ask below, I might give you an alternate to do so.

.find().html() in jquery always returning null when used inside iframe

I am trying to access data of the html document(contains a table) that I am opening in iframe.
I want to access table data.
//#we is id of a <td> #iframe is id of iframe
var q=$('#iframe').find('#we').html();
document.write(q);
But when i use this i always get a null value.help.
Make sure that the iframe is on the same domain, otherwise you can't get access to its internals. That would be cross-site scripting.
None of the browsers would allowing accessing iframe which is from a different domain than your site. It is a serious security breach. Thus if you are loading iframe from different domain, no matter what you do, you can't access it.
You might not like the answer, but it is the fact.
If your iframe is in fact on the same domain - you can use the following.
var q = $('#iframe').contents().find('#we').html();
Please try this:
var body = $('#iframe').contents().find('body');
or this can also be helpful:
$(editFrame).contents().find("html").html();
That should return all the html in the iframe for you. Or you can use "body" or "head" instead of "html" to get those sections too.

Update URL from inside an iFrame

is it possible for javascript inside an iFrame to update the URL (hash) of the parent page (and retrieve it)
Does it have any permissions?
To further explain, I have no hosting for this domain, I can only set up an Iframe. I also cannot use a DNS config to get that page to display because of limitations of my hoster.
I also cannot transfer the domain to them to make that work because my clients wants to keep control of the domain.
Thank you for your help!
If the <iframe> page is within the same domain, probably yes. Otherwise you don't get access to the parent page due to cross-domain restrictions.
You can change the URL of the parent page though:
top.location.href = 'http://www.example.com';
due to security constraints you will not be able to access properties of the parent window IF the domain,port or protocol is different than the one in the iframe.
To be short, the answer is NO.
Your script works only inside the context of that iframe.
If you try for example,
var loc = document.location;
you will see what I mean.
One solution is that when you give the other side your iframe, you should add a script in witch you can do whatever you want, because it runs on their domain.
Maybe dynamically create the source of your iframe and stuff.

Cross domain iframe content load detection

I have a rather interesting problem. I have a parent page that will create a modal jquery dialog with an iframe contained within the dialog. The iframe will be populated with content from a 3rd party domain. My issue is that I need to create some dialog level javascript that can detect if the content of the iframe loaded successfully and if it hasn't within a 5 second time frame, then to close the dialog and return the user to the parent page.
I have researched numerous solutions and only two are of any true value.
Get the remote site to include a javascript line of document.domain = 'our-domain.com'.
Use a URL Fragment hack, but again I would need the request that the remote site
able to modify the URL by appending '#some_value' to the end of the URL and my dialog window would have to poll the URL until it either sees it or times out.
Are these honestly the only options I have to work with? Is there not a simpler way to just detect this?
I have been researching if there's a way to poll for http response errors, but this still remains confined to the same restrictions.
Any help would be immensely appreciated.
Thanks
The easiest way (if you can get code added to the external sites) is to have them add an invisible iframe pointing to a special html file on your domain. This could then use parent.parent.foo() to notify the original window about the load event.
Listening for the "load" event will only tell you if the window loaded, not what was loaded or if the document is ready for interaction.
Nicholas Zakas has an article about detecting if an iframe loaded: http://www.nczonline.net/blog/2009/09/15/iframes-onload-and-documentdomain/. Basically you have this code snippet:
var iframe = document.createElement("iframe");
iframe.src = "simpleinner.htm";
if (iframe.attachEvent){
iframe.attachEvent("onload", function(){
alert("Local iframe is now loaded.");
});
} else {
iframe.onload = function(){
alert("Local iframe is now loaded.");
};
}
document.body.appendChild(iframe);
I haven't tested it, but I'm pretty sure jQuery should be able to handle it by doing something like $("#iframe").load(function () { alert("Local iframe is now loaded."); });
You could try using postMessage for communication between frames.
This will require the remote site to include some specific JavaScript to post a message to the parent document when it has finished loading.
It's possible to do this with an onload handler on the iframe itself. Unfortunately (surprise!) IE makes it difficult. The only way I could get this to work was to compose HTML for the iframe, then append it to the document with innerHTML. Then I have to poll to see when the iframe appears in the DOM, which varies depending on if the page is loading. Here's a link to the source: http://svn.openlaszlo.org/openlaszlo/trunk/lps/includes/source/iframemanager.js
See create(), __finishCreate() and gotload(). Feel free to take a copy of this and use it yourself!
Regards,
Max Carlson
OpenLaszlo.org
This is how I detected the loading of a Cross-Domain Iframe,
Set a unique id for the iframe ( U may use any sort of identifier, it doesn't matter )
<iframe id="crossDomainIframe" src=""> </iframe>
Set window event listener:
document.getElementById("crossDomainIframe").addEventListener('load',
function actionToPerform(){
//Do your onLoad actions here
}
)
In any case you will need some sort of cooperation from the other domain's server, as you are trying to abuse the Same Origin Policy (SOP)
The first solution document.domain=... won't work if domains are different. It works only for subdomains and ports, as described in the link above.
The only option that allows cross domain communication without polling is JSONP or script injection with a JS function callback. This method is available in all Google APIs and works well.
We've explained on our blog a way to sandbox those calls in an iframe to secure them. While postMessage is better now, the window.name hack has the advantage of working on old browsers.
Ironically, SOP does not prevent you to POST anything to another domain. But you won't be able to read the response.

Categories