Our web site makes use of showModalDialog. Based on what is done within the dialog, we may or may not wish to reload the page that opened the dialog. We do this by having the dialog JavaScript set window.returnValue to true or false, and then the underlying page inspects that in the return value of the call to showModalDialog.
This works fine when the dialog document and underlying page are loaded from the same origin domain. As is typical with the web, when the dialog's domain doesn't match the page's, the return value from showModalDialog is always undefined.
I've entertained passing the flag from the dialog to the underlying window in different ways. Fortunately, we're targeting browsers that all support postMessage, but the dialog JavaScript doesn't appear to be getting a value for window.opener, so I don't think it can get a reference to the window so it can post a message. Implementing an iframe workaround like this is unfeasible with our code base because it would require us to install iframe recipient documents on multiple sites that can all open this same dialog.
Is there a better way for us to have a dialog communicate with cross-origin opening pages without requiring that they reload?
I may have found my own answer. From what I understand, if I set the document.domain property for both the opener document and the dialog document to the same value, I should be able to access this information. Since both are within subdomains of the same root domain name, it should work. If I try this and it works, I will accept this answer.
Related
In our web app/site, I need to use an iframe or a popup window to validate if the current token is valid and refresh it if no.
So, I create an iframe, and set the property 'src' to the validation link such as "https://<domain_name>/auth?client_id=xxx" which is different to our app domain https://<app_domain>. and the return value will like "https://<domain_name>/code=yyyy"
document.createElement('iframe');
and I added the message handle for the web app/site, like
window.addEventListener("message", this.messageHandler);
in the messageHandler, I will check if the message is from a specified website, and then validate the "code" value, blabla, etc.
But when running in Chrome, I always got the error
"Blocked autofocusing on a element in a cross-origin subframe."
what confused me is:
it always failed when running in the Chrome browser, but it can work fine in Firefox and Edge chromium.
I tried to set iframe.sandbox = "allow-forms allow-scripts allow-same-origin", the problem still existed.
If the validating token failed in iframe or timeout, I will create a popup window to continue validating and refresh the token. But every time, using popup window can always succeed. If it is really a cross-origin issue, why using iframe failed but using popup window succeeded.
I didn't use window.postmessage. because I don't know how to pass the return value of iframe/popup-window to the main page.
I used CORS extension of Chrome or using parameter --disable-web-security when launching Chrome. the problem still existed.
when I created the iframe or popup window. it is very simple, I just set the iframe.src property, there is no element being created.
any help will be much appreciated.
p.s.
I refer to the following doc:
Blocked autofocusing on a form control in a cross-origin subframe
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
Support for iframes in web development will only get worse over time as they are a security black hole, browsers are gradually over time locking out features and use of them.
I am assuming you are doing this because you are validating a user on a third party service, validating by watching the response of a third party service website?
Without knowing the service you are using I cannot comment specifically but for anyone looking to do something similar I would highly suggest not doing this:
As mentioned, iframes are constantly having features locked down due to security concerns
An attacker could change the source of the iframe and submit their own iframe to look like it has been correctly validated
It's unlikely that the page you are using as your iframe src is intended for this use, which will come back and bite you when the 3rd party developer changes how their page behaves, which they likely will do without knowing it's going to break your application
I recommend:
Finding a stable API the 3rd party service offers and using that
Finding another service if none exist
Apologies to rain on your parade!
I disagree that iframes are a security risk, rather they can be if not implemented properly.
How to implement them properly should be asked in another question and probably starting with a carefully implemented Content Security Policy as a priority.
I also use iframes within a Chrome extension that has to pass rigorous Google security.
As for the question, I've noticed that error too and I am focusing on an input box when the iframe is loaded and the focus works! I put it down to being a Chrome bug as the warning suggests it has stopped auto focusing when it hasn't.
As for the un-related point about passing the value back to the parent holding the iframe, I can help you with that, but you should ask it in a new question.
Disable some feature of browser setting
Browser Changes
chrome://flags/#cookies-without-same-site-must-be-secure
chrome://flags/#same-site-by-default-cookies
chrome://flags/#enable-removing-all-third-party-cookies
Above URL just paste it and disabled it. Then ok and relaunch the browser.
Then done it.
I have a look at these two questions and i don't understand.
Redirect parent window from an iframe action
How to prevent IFRAME from redirecting top-level window
On one hand it appears that you can redirect the parent iframe and on the other you cannot?
When i try it, I have no problem redirecting the parent frame so i'm curious as in why everyone say you cannot redirect parent frame unless you are on the same domain. But I can redirect without having the frame on the same domain.
As stated previously, will redirect the parent iframe. One thing to bear in mind is that both the website, and the site contained in the iframe need to be on the same domain for this to work, or you'll get an access denied exception.
Is it browser related?
Edit
I have two pages and this works but shouldn't :
On domain 1
<html>
<body>
<iframe src="http://domain2.fr"></iframe>
</body>
</html>
On domain 2
<html>
<body>
<script type="text/javascript">
window.top.location.href = "http://google.fr";
</script>
</body>
</html>
The answer to Why it is possible is perfectly simple. window.location is part of the Web API, which is not exactly the same as the JavaScript core. It's part of the DOM interface, hence it's gouverned by W3C, not ECMA. That's why it allows you to manipulate the top-window's properties.
Strictly speaking, JS isn't capable of doing this, because it lacks IO capabilities, which makes the language extremely portable. That's why browser implementations require the DOM API, to query the DOM, and request repaints or interact with the client. The DOM, though, does need IO, because it renders, and reads from the actual UI. Some people in the ECMAScript committee would rather have seen the access to the window.top heavily restricted, if not removed all together, for XSS vulnerability reasons. Sadly W3C agreed to disagree, and implemented the window.top reference anyway.
Who's right or wrong in this case? I don't know, it's easy to redirect a client to a malicious site from within an iFrame, which is unsafe. But it would be frustrating to have an iFrame, and then not having access to the top window, which would mean not being able to interact with the client as easily. But that's not the point here. Bottom line is, you can change some top window properties, and it can be useful. Just think about mashups. They pose a lot of challenges in terms of XSS safety, but open up a lot of new and exciting possibilities for webaps. To plug some of the most dangerous XSS vulnerabilities, take a look at ADSafe, which was created by Douglas Crockford. Google has a similar lib, but I forgot its name ATM...
the Same origin policy doesn't apply here, either. By changing the url in the address bar in your browser window, you're changing the window.top.location.href property, too. If there were same-origin restrictions there, the internet would be dead. You're not sending a request to another location, you're not getting data from a third-party resource and loading it in your page, you're redirecting the browser to another location, which closes and clears the DOM.
My guess is that it is the same reason you can do the following:
Redirect top to Google
I found the rules for this behavior here: http://www.w3.org/TR/html5/browsers.html#valid-browsing-context-name-or-keyword
I couldn't find a "why", but personally I have found it useful to redirect the parent after someone has clicked on something within an iframe. You may want to first perform an async operation and validate something before redirecting the entire page. Since this is already possible using the <a> tag perhaps it was found appropriate in JS as well. Not sure why the <a> tag allows the functionality though.
That being said you can always prevent this behavior by adding sandbox="" attribute, example: http://jsfiddle.net/ppkzS/1/
Whenever you use iframes, frames, or objects, you set up a hierarchy of windows, with these items acting as "window"s in this hierarchy.
You can traverse this hierarchy with properties such as .parent, .frameElement and the like. The property .top is the window at the highest point in the hierarchy and usually corresponds to the outermost frame.
Some actions are prohibited between windows in the hierarchy, others are not. Changing the location of a window is not prohibited.
Ultimately, people who say you cannot do this are incorrect. What you can't do is access the contents of one window from a different window if their domains differ. However, you can modify their location properties.
If you have two frames on the same domain (and also same protocol and port too), then one frame can redirect the other to wherever you want, and also access javascript properties, execute function from the other frame, etc.
Should you redirect one frame from the other to another domain (or protocol, or port), then you would lose the ability to do all that I previously stated due to the Same Origin Policy, but the redirect itself is allowed because, before the redirect, the two frames satisfied said policy.
Here is some useful information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript
Quoting from that page:
Two pages have the same origin if the protocol, port (if one is
specified), and host are the same for both pages.
Obviously, frames is the same as pages.
I'm designing some "add-on" to certain websites, which should be embedded in them as an iframe. Inside this iframe there is a clickable button aimed at changing the iframe's position within the parent website.
Since things are done in coordination with the parent website, I am able to add some code there as well. However it seems I am not able to do neither of the following (one of them should suffice):
From the iframe, access data within the parent.document, in order to move the iframe to the desired position.
From the parent website, access data within the iframe, in order to check when the button is clicked.
Both typically produce an error: "Blocked a frame with origin XXX from accessing a frame with origin YYY. Protocols, domains, and ports must match".
Any advice (preferably with code sample) is appreciated.
After doing lots of searching around, I came across this:
http://www.codeproject.com/Tips/585663/Communication-with-Cross-Domain-IFrame-A-Cross-Bro
I actually tested the method (using my own short piece of code) and it seemed to work on Chrome, Firefox and IE. Now I'm gonna try the "real" implementation...
From what I understand based on the information you've provided in your question, cross domain scripting is not possible. What you would need to do is provide a script that the parent-level website can paste into their template/html and run from their domain, similar to how Google does with their analytics system.
As an alternative, try turning your iframe content instead, into a div loaded with the response from a service call made from the parent domain to the iframe domain. You would most likely need to create an API that a requesting site can use. Simply call that URI with whatever parameters you would use when referencing the page you wanted to load in the iframe, and have the script that you run on the parent website handle all the DOM alterations you want to achieve.
I would like a javascript to run after a page is loaded , like on the example below with a delay of 6seconds. Right after the page loads the rest of JS is lost (obvious)...
Got any ideea how change content after page is loaded without clicking a button?
javascript:window.location = "http://example.com";
setTimeout(function() {
document.getElementById('lightbox').style.display = 'none';
}, 6000);
Once you set window.location the original page will be unloaded before the new page is loaded by the browser. This means your script will be gone before the new page start loading and thus can't modify the new HTML anymore.
This behavior is inherent to the security model of the browser. Without it you could inject any JavaScript into any web site of your choosing, which would be a huge security risk. What you are asking for is so-called XSS (for cross site scripting), which is prevented by the browser applying a so-called SOP (for same-original policy).
There are some common ways to work around this limitation in a safe way:
Set up a proxy to serve both your JavaScript and the original site. This way both your script and the original site come from the same domain and satisfy the browser's same-original policy (SOP). You could run the original site in an iframe with your custom script occupying the top-level window. Alternatively you could inject your script into the HTML as it is being retrieved through your proxy.
Run your script as a browser add-on or user-script. If you choose to do this, the user will have to specifically grant your script the rights to run locally with elevated rights. Greasemonkey popularized client-side scripts for Firefox a few years ago, but recently they seem to have lost momentum.
Ask the site owner to include your script. I doubt this is a valid option for your situation. But if it is a valid option it is definitely the simplest one.
Ask the user to run your script after the site has loaded. This one is probably also not valid for you, but if valid it would once again be a very simple solution.
Your example shows that you are first redirecting and then attempting to hide #lightbox. This script would not work, because you are redirecting the browser to another site before #lightbox gets hidden.
In short, you cannot have Javascript of a previous page manipulate DOM of the next page if you redirect the user to another URL (or even the same URL). Only Javascript that is 'on currently open page' can manipulate currently open page and no other pages.
I have not understood what you are saying. JS is lost? Please be more clear.
I think what you are talking about is the jquery ready function which runs after the DOM is ready. Or in the other case, try using window.onload() function.
This should do the job:
$(window).bind('load', function() {
// your code here
});
Then simply add the delay to your added code with .delay("6000");
The inserted code will only run when your page is completely loaded.
Suppose I have a page that I am writing a javascript plugin for on the domain first.com. The javascript plugin injects an iframe pointing to a login page (of domain second.com) into the first.com page and displays it as a popup so that the user can login.
Is there anyway for me to hide/close the iframe after the user logs in with it? I can inject any javascript necessary into the first.com page and I control both the client and server side code on the login page within the iframe.
The main issue is that the iframe cannot access it's parent window to hide itself and the parent window cannot see any changes made in the contents of the iframe because of the same origin policy. Is there anyway around this or should I just lose the iframe idea and instead open a new window?
If the developer of second.com can be convinced to load an iframe in their login page, which loads a page at first.com, the the inner iframe can call javascript on the outer, since they are both from first.com. You can pass parameters in this way too, through the url of the inner iframe. An example here.
I think the issue you're running into is the browser stopping the cross-domain communication from happening. There is a way to sign your javascript but it is pretty much breaking the browser security model and isn't suggested unless absolutely necessary.
Is there any way that the login form is based on URL submition? You could create a simple sign in form and use AJAX to get your response back to ensure a successful login. This solution depends on having a RESTful login and again, I'm not sure about the implementation of your second.com.
If you're wondering about how to use the ajax to submit a form, I'd check this out (it is in jQuery but it applies to just about any framework.) View the source on that and see if that could work in your situation.