Login popup vs lightbox in Facebook canvas app - facebook

I have a Facebook canvas app, which calls FB.getAuthResponse() first and, if necessary, FB.login(). The documentation of the JS SDK clearly states FB.login() opens a login popup window, which is correct when I hit the canvas URL directly. However, when I do the same thing in the canvas page as an anonymous user a "Not logged in" lightbox appears and redirects to the login page.
Is there any way of unifying this behaviour (preferably always using popup)?

Turns out it's possible to explicitly specify the 'format' of the login window when using JS SDK - FB.login() accepts the display parameter which defines the display mode of a window.
The final code looks like this:
var authResponse = FB.getAuthResponse();
if (authResponse && authResponse.signedRequest) {
addFieldsAndSubmit(authResponse.signedRequest);
} else {
FB.login(function(response) {
if (response && response.authResponse) {
addFieldsAndSubmit(response.authResponse.signedRequest);
}
}, {scope:'email', display: 'popup'});
}

Related

Chrome blocks FB.login()

I have a FB app which need to be integrated in a FB page tab. In app I want to provide a "Signup with FB login" option. This button when clicked should prompt the user to login into FB login dialog. On successful login it should prompt the user to authenticate and allow the app to use his details. Once the user allows the app to access the user details it should then post the details to my website in a new window.
This process works fine when I test the app independently. However when I add the app to the fb page, chrome blocks the Fb login dialog. Before opening the Fb login dialog I check if the user is already logged in FB and has accepted the app. For that I use FB.getLoginStatus(checkLoginStatus); I figured due to this check the context moves to script execution and hence Chrome blocks the login dialog.
Is there a work around for this issue? Help would be highly appreciated.
My code is as follows:
The facebook button is created using span and the id fbc-login-button is given to an a tag.
$("#fbc-login-button").click(function(){
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
console.log('Logged in.');
if (response.authResponse) {
fbAppSignup(response);
}
}
else {
FB.login(function(response) {
if (response.authResponse) {
fbAppSignup(response);
}
},{scope: "email, user_friends",display:"popup"});
}
});
function fbAppSignup(response,myPopup){
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
FB.api("/me", function(response) {
$("#social_media_data").val(JSON.stringify(response));
$("#medium").val("facebook");
$("#accessToken").val(accessToken);
$("#socialClickSource").val("fbapp_facebook_signup");
$("#fbSignUp").submit();
return true;
});
}
The example in the Facebook docs is a bit misleading, you should never use FB.login in an asynchronous callback function - and that is exactly what you are doing right now, because FB.getLoginStatus is asynchronous. Always call FB.login on user interaction (mouse click) or it will get blocked by intelligent browsers.
FB.getLoginStatus: on page load, for refreshing the user session and
checking if the user is authorized already
FB.login: on user interaction
Other threads i´ve answered about that problem:
Facebook login popup blocked
FB.api response callback async popup blocked
Sign In with FB issue: FB popup window with the Login dialog is blocked by a web browser

FB.login() popup blocked only in mobile web application

For our mobile web application using the Facebook Javascript SDK, we want to check the user's login status, and then display the Facebook login dialog if necessary. The following code is run within a click handler for a given button in our web app:
$('#button').click(function() {
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
// do something with the logged in and authorized user
} else if (response.status === 'not authorized') {
// logged in but has not authorized our app
} else {
// not logged in
FB.login();
}
});
});
Ensuring that the user is not logged into Facebook, this works fine and displays the login dialog for desktop web browsers when the button is pressed, but not for the mobile web (at least not for Android on a variety of browsers, I don't have access to an iPhone currently). Nothing appears on the mobile web app, and when I disable the popup blocker, then I get a prompt asking if I want to allow this popup, which works.
Does anyone know why the behavior is different and/or what the known/standard workarounds are? Thanks!
Your code will not work in all desktop browsers. Some browsers (mobile and desktop) block popups unless they are initiated by a user click. For example,
$('#mybutton').click(function() {
FB.login();
});
will work because the FB.login() function is only being called in response to the user's click. So to fix your code, replace the FB.login() call with some code that displays a 'login' button and text encouraging the user to click that button.

User permission dialog doesn't pop-up for tab application

I have a strange behavior for an application that I have implemented and that captures the user's info when accessed.
The application, if accessed from outside Facebook URL, pops-up correctly a JavaScript permission dialog.
But when I inserted this application as a tab application into a Facebook page the permission request dialog doesn't pop-up anymore. Moreover, I have also placed in an FB.getLoginStatus() implementation the detection of the user's current login status in Facebook, with a JavaScript alert pop-up window if the user is not logged in. When the application is called from 'outside' the alert is triggered. When the application is on a Facebook page tab it doesn't.
Is this the correct behavior? If so, how can I enable the permission request in a Facebook tab application. I'm using both JS and PHP Facebook SDKs.
Edit 1 (following CBroe comment):
I'm using the following calls in the application's content.php markup (executed on page load):
<!-- Facebook JS SDK initialization -->
<div id="fb-root"></div>
<script>initFacebookJSSDK();</script>
<!-- End of Facebook JS initialization -->
<script>checkAccessPermission();</script>
<?php include_once 'sites/www.mysite.com/custom_code/custom_index.php';?> // I'm doing
custom code under Drupal
The JavaScript functions are implemented in the custom.js file, as following:
function initFacebookJSSDK() {
window.fbAsyncInit = function() {
FB.init({
appId : 'xxxxxxxxxxxxxxxxxx', // Application's ID
channelUrl : 'www.appsite.com/channel.html', // Channel File
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true, // parse XFBML
oauth : true // enable OAuth
});
.........
});
.........
}
function getPerms() {
FB.login(function(response) {
if (!response.authResponse) {
//user refused to grant permissions, redirect to the 'index' page
window.location = "/index";
}
}, {scope:"email"}); // I request the permission to get the email address
}
function checkAccessPermission() {
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
//user has granted permissions to the application
var uid = response.authResponse.userID; // not used
var accessToken = response.authResponse.accessToken; // not used
}
else if (response.status === 'not_authorized')
// user is logged into Facebook but didn't grand permissions to the app
getPerms();
else {
//user has not granted permissions, redirect to the 'index' page
alert('Please connect with your Facebook account');
window.location = "/index";
}
});
}
The PHP script - file 'custom_index.php' contains the following snippets:
$config = array();
$config["appId"] = FB_APP_ID;
$config["secret"] = FB_SECRET_ID;
$config["cookie"] = true;
$facebook = new Facebook($config);
// get user UID
$fb_user_id = $facebook->getUser();
// user's first visit, force the permission request window
if ($fb_user_id == 0) {
$location = $facebook->getLoginUrl(array('scope' => 'email'));
..........
}
// user already gave permission, get the profile and process
if ($fb_user_id != 0) {
$access_token = $facebook->getAccessToken();
$user_profile = $facebook->api('/me', array('access_token'=>$access_token));
..........
}
Again, it works very well when the user visits the site outside Facebook, but the permission request pop-up window doesn't show-up when it runs as Facebook tab application (frame inside Facebook). To note that, concerning my previous posting, now the JavaScript statement:
alert('Please connect with your Facebook account');
is executed in both cases, including when the application is run as tab app inside Facebook (I had just to clear the browser's cache).
Here is the solution.
All the code above is correct and stays in place.
I just added a jQuery function on the link that pulls-up the 'content.php' page, as following (the class '.open-content-page' is on the parent page of 'content.php'):
$(document).ready(function () {
$(".open-content-page").click(function() {
checkAccessPermission();
});
});
})(jQuery);
You’re calling your JS function without any user interaction – have you made sure it’s not just your browser’s popup blocker that keeps the dialog from coming up? (Maybe it distinguishes between popups called from a „simple” page vs popups from pages embedded in iframes on other domains.)
Since you can’t rely on your site’s users having their popup blockers set very liberal, it’s generally a better idea to call facebook dialogs on user interaction, f.e. when the user clicks a link/button. Popups called on user interaction are less likely to get blocked than popups that want to open all by themselves.

Facebook redirect after login

I have read a number of questions and answers, including this one on StackOverflow and none works. My question to all responses I have seen are 'does it work in Safari?'.
I am trying to get this to work with Safari. It works on Chrome and Firefox fine. But in Safari the login screen just freezes and I get the "Unsafe JavaScript attempt to access frame with URL" log message.
I have a canvas app. I want to log the user in and redirect them to a page once they have logged in. I am trying to redirect directly after login. I have tried
setting window.top.location to a facebook url (with some data passed to a signed request as the all_data argument)
setting window.location to a URL with the same domain as my app.
subscribing to the auth.login event and putting the redirect there
putting the redirect in the callback to login
None of these works for Safari. I'm starting to think that there's no way to do it.
function doSomething()
{
FB.login(
function(loginResponse)
{
if (loginResponse.authResponse)
{
window.top.location = "my url"
}
},
{
scope:"some,scope"
}
);
}
}
In response to Nitzan Tomer, here is the equivalent code which doesn't work with Safari but does work with others:
function myThing()
{
FB.login(function(loginResponse)
{
if (loginResponse.authResponse)
{
FB.api('/me', function(response)
{
window.location = "http://my_app.com?x=" + response.xyz;
});
}
},
{
scope:"scopes"
}
);
}
This is not much of a solution to your problem, but more of a "workaround", though it still uses window.top.location but not from a callback so maybe it will work (I'm just not sure where the callback is executed, since it's the fb sdk that executes it, maybe they call it from the fb iframe inside your iframe).
Instead of using client side authentication, you can use the server side flow.
The entire process is happening on the top window, since it starts by you redirecting the user to the oauth dialog using window.top.location.
When the process ends facebook redirects the user to your redirect_uri, and there you can simply redirect the user where ever you want.
I hope this will help.
Also, you should be aware that in the Facebook Platform Policies it states:
13 . The primary purpose of your Canvas or Page Tab app on Facebook must not be to simply redirect users out of the Facebook experience
and onto an external site.
It turns out the problem was occurring slightly earlier in the login process and the callback never got called. I did set a breakpoint in the callback (which wasn't called) but I thought the breakpoint might not work for some reason (perhaps because it was being executed in the context of another window).
Anyway, the problem was that the channel file (which the docs seem to suggest are optional) wasn't working properly, and this caused a problem with Safari but not with other browsers.

How to show the Extended Permission Dialog in FB using new Graph API?

I used the old rest api for showing the Permission Dialog in Facebook before.
Now, with the new graph API, what can I do? (I'm in IFrame Apps).
I know that I can cheat and popup the permission in a seperate window:
FB.login(function(response) {
if (response.session) {
if (response.perms) {
// user is logged in and granted some permissions.
// perms is a comma separated list of granted permissions
} else {
// user is logged in, but did not grant any permissions
}
} else {
// user is not logged in
}
}, {perms:'offline_access'});
like that.. call the FB.login again (let say I want people to click on a different button and trigger the extended permisison dialog)
However,it looks ugly,and it doesn't look like a dialog.
Is there a way to generate the dialog? I try to figure out whether FB.ui can help but there is only little information about that.
In addition, I don't think the 'response' callback ever execute. Neither I click "Don't allow" or "allow", won't trigger any call back. any idea?
hihih..anyone can help me?
Finally. find out the solution from another website.
first. after FB.init( ... ); do that:
FB.provide("UIServer.Methods",
{ 'permissions.request' : { size : {width: 575, height: 300},
url: 'connect/uiserver.php',
transform : FB.UIServer.genericTransform }
} );
Then, whenever you need to call the permssion dialog, do that:
FB.ui({method: "permissions.request", "perms": 'email,offline_access'},
callBack);
It took me so long to figure out by looking at the FB object and find out there is UIServer with permissions.request then from that, I keep searching and find this solution. and FB.ui talks nothing about it.. and FB.provide is not documented. THANKS facebook.
You don't need to use javascript or any SDK for this although it would make it easier. You need only to redirect the user to a url like this:
https://graph.facebook.com/oauth/authorize?
client_id=...&
redirect_uri=http://www.example.com/callback&
scope=user_photos,user_videos,publish_stream
You should always redirect the user to the top window either with javascript or the link.
window.top.location = <login_url> or Login
If you are using the PHP SDK or the C# SDK you could have the sdk generate the url for you, but the process is the same.
Also, not that the redirect_uri has to be on the same domain as your iFrame application's url. This will cause Facebook to redirect your user outside of Facebook to your website, you then should redirect the user back to the app inside of facebook. For example:
User clicks login
user goes to Facebook login page
User clicks allow
Facebook redirects the user to http://www.example.com/callback
Your app redirects the user to http://apps.facebook.com/myapp/loggedin
One of the answers suggests a hack in which you call FB.provide() and then FB.ui() to pop up the extended permissions dialog. That solution doesn't work for me, but there is a documented solution now that does. Just call FB.login() to get the permissions you need.
FB.login(function(response){
if (response.authResponse) {
alert('success!');
} else {
alert('fail!');
}
},{scope: 'email'});
Even better, you can ask for extended permissions with the login button.