Unsafe JavaScript attempt to access frame...Protocols must match - javascript

Here's my situation: I have a Javascript plugin that when clicked launches a popup on the third-party sites that host it. That popop then displays an IFRAME, in which I am using Facebook as a login method.
When the popup is launched, it recently started giving an error:
Unsafe JavaScript attempt to access frame with URL
http://{THIRD-PARTY-SITE-GOES-HERE} from frame with URL
https://s-static.ak.facebook.com/connect/xd_arbiter.php?version=18#channel=…%3Dtabmodule%26utm_term%3D200000%26fb_xd_fragment%23xd_sig%3Df2ade8e518%26.
The frame requesting access has a protocol of 'https', the frame being
accessed has a protocol of 'http'. Protocols must match.
The IFRAME itself is on https and used to work properly. I'm not sure why Chrome is trying to access the parent page. I have no control over the parent pages, so I can't make them https.
Here is my FB init code from within the IFRAME:
window.fbAsyncInit = function()
{
FB.init({
appId: '{myappid}',
status: true,
cookie: true,
xfbml: true,
oauth: true,
channelURL : 'https://degree3.com/channel.php'
});
FB.getLoginStatus( function(response)
{
if (resp = response.authResponse)
{
$( '#fb_button' ).attr( "onclick", "signinViaFacebook( response.authResponse.userID, response.authResponse.accessToken );" ).show();
}
});
};
(function()
{
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
}());
Any ideas how I can fix the error?

You can't use facebook login inside an iframe it will never work. Dont even bother trying I have spent several frustrating hours trying to do the same. Even if you solve the https problem you have right now, you will then face an X-Frame Options error because of an option set in the response header by facebook which accepts only requests from same origin(that is facebook).
What I'am basically trying to say is that facebook cannot be launched in an Iframe for security reasons. Your best bet in your current predicament is to open another popup with facebook login in it. Iframe simply wouldn't work. I know it wouldn't look elegant but it is the only way to go or you redirect your popup itself to facebook and have a callback mechanism to redirect back to your plugin.
Hope it helps.

Related

Facebook share APi not working

I try to share a page using this code
FB.ui(
{
method: 'share',
href: 'https://developers.facebook.com/docs/'
}, function(response){})
after i run this Initialization code
FB.init({
appId : 'my-app-id',
status : true,
cookie : true,
xfbml : true,
version : 'v2.1'
});
And it works only the first time i press the button on my page. the next time I'm trying to
click the button that call the FB.ui function i get this error in the console
Uncaught SecurityError: Blocked a frame with origin "https://s-static.ak.facebook.com" from accessing a frame with origin "https://www.mywebsite.com". Protocols, domains, and ports must match.
If i run the page in incognito mode everything works fine.
I tried a number of solutions presented here on the site and I could not solve the problem
Does anyone have suggestions ?
I found out that FB.getLoginStatus function can't work good with the FB.ui function.
so i solved the problem by creating function that open share windows instead of using the FB.ui function
function facebook_share(link){
var left = (screen.width/2)-(520/2);
var top = (screen.height/2)-(430/2);
window.open("https://www.facebook.com/sharer/sharer.php?u=="+link, "_blank", "toolbar=yes, scrollbars=yes, resizable=yes, top="+top+", left="+left+", width=520, height=430");
}

postMessage in PhoneGap not working - iframe to parent messaging

I've build a PhoneGap app which which makes use of an iframe which is bundled with the app and I'm am trying to pass e message from the iframe to the parent which doesn't seem to be working when I run the app on an actual iPad; however it works fine when I run the app in the browser on the same device.
Here is the code I'm using inside the iframe to send a message, note that I'm using HammerJS to capture some events:
var domain = 'http://' + document.domain;
$('body').hammer().on("swipe", "", function(event) {
var message = event.gesture.direction;
parent.postMessage(message,domain); //send the message and target URI
});
and the code I'm using to get the message:
window.addEventListener('message',function(event) {
alert(event.data);
},false);
And the answer is to use "file://" as the domain name so the code will look like this:
var domain = 'file://';
$('body').hammer().on("swipe", "", function(event) {
var message = event.gesture.direction;
parent.postMessage(message,domain); //send the message and target URI
});
Try with using
var domain = '*';
Normally this should be because of cross domain problem, see more here
You will need to use:
parent.postMessage(message,"*");
Since phonegap/cordova pages are served at "file://" and according to https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
"...posting a message to a page at a file: URL currently requires that the targetOrigin argument be "*". file:// cannot be used as a security restriction; this restriction may be modified in the future."

Executing a script via AJAX on Firefox OS device

My question regards the Apps CSP https://developer.mozilla.org/en-US/Apps/CSP
Here it says that all the remote script, inline script, javascript URIs, and other security issues won't work on a Firefox OS app.
So, I tried to download a script that is necessary for my app (Flurry and Ad service) and neither would work on the device. The way I made the call was with AJAX, that way I would avoid the remote and inline scripting that both scripts ment. In the simulator works perfectly, but on the device the ads never show and the Flurry session never starts.
Here is the part of my code where I make the AJAX call for Flurry:
$.ajax({
url: 'https://cdn.flurry.com/js/flurry.js',
dataType: "script",
xhrFields: {
mozSystem: true
},
success: function(msg){
console && console.log("Script de Flurry: luego de la descarga en AJAX "+msg);
flurryLibrary = true;
FlurryAgent.startSession("7ZFX9Z4CVT66KJBVP7CF");
},
error:function(object,status,errortxt){
console && console.log("The script wasn't downloaded as text. The error:" +errortxt);
flurryLibrary = false;
},
always: function(object,status,errortxt){
console && console.log("The script may or may not be downloaded or executed. The error could be:" +errortxt);
}
});
In my app I use the systemXHR permission and make the calls for other websites using this line:
request = new XMLHttpRequest({ mozSystem: true });
Wich is the same as using the xhrFields{mozSystem:true} in the AJAX call.
I believe it's not a cross domain problem because in the rest of my app I make calls for xml files that are not in my domain, and the calls are returned succesfully.
So, my question is, can a Firefox OS app execute scripts that are downloaded via AJAX? Is there a way to get around this problem?
Thank you for your time.
PS: I forgot to add that my app is privileged, just in case you ask
I believe that is a security feature and the short answer to your question would be NO. To quote the CSP doc that you linked to yourself:
You cannot point a at a remote JavaScript file. This means that all JS files that you reference must be included in your app's package.
If you load a JS file using ajax from a remote server, that JS is not included in your app package. You should be careful to obey CSP restrictions. It is possible to get many things working in the simulator or even the phone while developing without fully complying to CSP, but that does not mean it is OK. When you submit your app in future to any credible marketplace (such as Firefox Marketplace), it will be reviewed carefully to make sure it does not violate CSP restrictions. As a general rule of thumb, I would say any attempt at dynamically evaluating JS code will be a security risk and most likely banned by CSP regulations.
First, I'll point out that your two examples are not equivalent.
$.ajax({
xhrFields: {
mozSystem: true
},
});
Is the same as
request = new XMLHttpRequest();
request.mozSystem = true;
which is not the same as
request = new XMLHttpRequest({ mozSystem: true });
Instead, we can follow the advice in the linked bug report and run the following at application load time:
$.ajaxSetup( {
xhr: function() {
return new window.XMLHttpRequest( {
mozSystem: true
} );
}
} );
This alone should fix your problem. However, if it doesn't work, then the next workaround here is to fetch the script resource as plain text and then load that text content as a script.
However, inline scripts and data: URLs are off-limits for privileged Firefox OS apps. We might still accomplish this goal through a blob: URL, however:
window.URL = window.URL || window.webkitURL;
var request = new XMLHttpRequest({ mozSystem: true });
request.open("GET", "https://cdn.flurry.com/js/flurry.js");
// when the Ajax request resolves, load content into a <script> tag
request.addEventListener("load", function() {
// make a new blob whose content is the script
var blob = new Blob([request.textContent], {type: 'text/javascript'});
var script = document.createElement('script');
script.src = window.URL.createObjectURL(blob);
// after the script finishes, do something else
script.addEventListener("load", function() {
flurryLibrary = true;
FlurryAgent.startSession("7ZFX9Z4CVT66KJBVP7CF");
});
document.body.appendChild(script);
});
However, if the script itself does something not allowed by the CSP, then you're definitely out of luck.
You must use mozSystem and mozAnon properties, example:
var xMLHttpRequest = new XMLHttpRequest({
mozAnon: true,
mozSystem: true
});
Its a shame this is a problem, I was hoping on getting loadScript working, as firefoxOS is an environment, and in my app all the application code is HTML5 and local, the current rule is all the scripts need to be loaded in memory in one shot, unless you url load a full page, which means you can not have a persisten wrapper around the site, and ajax inthe pages with assosiated scripts when needed. you would have thought that firefox would have enabled local lazy load for scripts at least. works in chrome, but not in firefox.

Secure/Non-secure browsing issue

I am developing a Facebook app that incorporates our Brightcove (video host) players and their API. Facebook gives users the option to browse securely and this poses a little bit of a problem. As is stands, I can get the app to work properly on one of the protocols (http or https), but not both.
https://www.facebook.com/atlantafalcons?sk=app_292392080815275 (change to http:// to see it not working)
If I set the BrightcoveExperiences.js file source to https://sadmin.brightcove.com/js/BrightcoveExperiences.js then it throws errors when someone is not browsing securely. If I set it to http://admin.brightcove.com/js/BrightcoveExperiences.js then it throws errors when someone is browsing securely.
The documentation for embedding securely is here: http://support.brightcove.com/en/docs/publishing-brightcove-player-https-page
Is there a way to detect if the user is browsing securely to be able to choose which JS file to load or is there a way to force users to browse securely? Or is there another workaround for a problem like this?
Thanks in advance!
EDIT:
Was able to come up with a solution (thanks to scibuff for recommending to check google analytics):
<script type="text/javascript">
var bJsHost = (("https:" == document.location.protocol ) ? "https://sadmin." : "http://admin.");
document.write(unescape("%3Cscript src='" + bJsHost + "brightcove.com/js/BrightcoveExperiences.js' type='text/javascript'%3E%3C/script%3E"));
</script>
Use a scheme-relative URI:
//admin.brightcove.com/js/BrightcoveExperiences.js
And don't use different hostnames for the SSL and non-SSL instances.
(Or have sadmin respond with a 301 redirect to admin for non-SSL requests)
I would go with Quentin's suggestion. Although, using your suggestion, you can use:
// window, top, self, document, others?
window.location.protocol
In other words:
if (window.location.protocol == 'http:') {
document.body.innerHTML = 'The page is using the http (non-secure) protocol.';
} else {
document.body.innerHTML = 'The page is using the https (secure) protocol.';
}
http://jsfiddle.net/3NREg/
Other window/document objects might work as well, depending on what you need:
// window, top, self, document, others?
if (self.location.protocol == 'http:') {
document.body.innerHTML = 'The page is using the http (non-secure) protocol.';
} else {
document.body.innerHTML = 'The page is using the https (secure) protocol.';
}
http://jsfiddle.net/3NREg/1/

Calling FB.login with to get permissions throw an error in IE

I'm calling in canvas:
FB.login(function(){}, {
scope:'publish_stream'
});
On Firefox and Chrome shows popup with permission dialog. But on IE there is error (see attach.) :
An error occurred with my_app_name. Please try again later.
My FB.init:
FB.init({
appId: <FB_APP_ID>,
status: true,
cookie: true,
xfbml: true,
oauth: true,
hideFlashCallback: function(){}
});
Earlier (before oauth) I was using code below, it was ok, but it not work wit oauth:
FB.ui({
method: 'permissions.request',
perms: 'publish_stream',
}, function(){});
edit:
Information from access token:
edit2:
If you will find a solution, write answer - if it will work, I'll give you 100 points from my reputation.
To make it work in IE, you should add channelUrl param to your FB.init with fully qualified url. For example:
FB.init({
appId: <FB_APP_ID>,
status: true,
cookie: true,
xfbml: true,
channelUrl: 'http://www.example.com/facebook-channel.html'
});
The url must point to a page that contains just only one script tag:
<script src="http://connect.facebook.net/en_US/all.js"></script>
It's important to make channelUrl an absoulte, if you just write
channelUrl: '/facebook-channel.html'
It wont work. I've got a lot of headache with it, so I hope it'll be helpfull for you or anybody who troubled with it like me before.
Try to switch _inCanvas to true and see what happens
FB._inCanvas = true;
I also had this problem in the past. You are probably opening it on a domain that is not the same as the one specified as your site domain on the application settings page.
If you have selected to use
sandbox
in developers.facebook.com/apps.
You should change it to not use.
Now you’re running on https you will need to reference all assests over https. IE will now show a load of warnings telling the user not all content is sent over the secure connection. This is probably why your popup fails. Set the SDK to load stuff over HTTPS:
FB._https = true;
FB.init({
/* your app id and stuff */
});
maybe it's because IE not setting 3rd party cookies?
try adding
header('P3P: CP=HONK');
into php file, header function has to come before anything in file is output.
I done walkaround for that. I'm opening new window with url like:
https://www.facebook.com/dialog/oauth?client_id=APPID&scope=publish_stream&redirect_uri=MYPAGE
When MYPAGE (which is in my app url) is loaded it simply closes itself.
If you will find a solution, write answer - if it will work, I'll give you 100 points from my reputation.

Categories

Resources