Emberjs: check if user is logged with facebook on init - facebook

I'm trying to use Facebook to log in an Ember application. The login action is working, but I can't find how to check if the user has already logged in when the app is initialized.
I'm calling the auth.authResponseChange event but it blocks the app and it never starts.
App.ApplicationController = Ember.Controller.extend({
fbUser: false,
init: function() {
this.checkFBUser()
},
checkFBUser: function() {
FB.Event.subscribe('auth.authResponseChange', function(response) {
// this is never triggered and the app does not init
console.log(response)
if (response.status === 'connected') {
console.log('Logged in')
}
else {
FB.login()
}
})
},
// this works
actions: {
loginFacebook: function() {
var self = this
FB.login(function(response) {
if (response.authResponse) {
FB.api('/me', function(response) {
self.set('fbUser', response)
})
}
})
}
}
})
How am I supposed to do this?

I haven't worked with FB lately, but I'm pretty sure the AuthResponeChange event is for being notified of a change in the AuthResponse status; in this instance you'll probably want to take a look at FB.getLoginStatus instead.
https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus
checkFBUser: function()
{
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
// the user is logged in and has authenticated your
// app, and response.authResponse supplies
// the user's ID, a valid access token, a signed
// request, and the time the access token
// and signed request each expire
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
} else if (response.status === 'not_authorized') {
// the user is logged in to Facebook,
// but has not authenticated your app
} else {
// the user isn't logged in to Facebook.
}
});

I've found the source of the problem and a solution. I'm not sure this is the best solution so I'm open to other suggestions but if this can help other people, here is the thing:
The issue was that the Facebook library was not loaded yet, so the FB variable was undefined. For some reason if you try to do something with an undefined variable in Ember the app just won't work without even a warning. So the solution is to wait:
App.deferReadiness()
function checkFB() {
if (typeof FB !== 'undefined') {
APp.advanceReadiness()
}
else {
setTimeout(checkFB, 10);
}
}
setTimeout(checkFB, 10);
10 milliseconds is pretty short so the app is still initialized very quick, and in my tests the app starts after ~20 milliseconds. This still feels a bit hacky but in place of a better solution this will do for now.

As Aaron said you need to use fb.getLoginStatus to check if a user is already logged in. To make sure Facebook is loaded before you to make any calls you can use an initializer and defer the app until the SDK has loaded.
http://nerdyworm.com/blog/2013/04/03/ember-initializers/
Ember.Application.initializer({
name: 'init_fb',
initialize: function (container) {
window.App.deferReadiness();
Ember.$.getScript( '//connect.facebook.net/en_UK/all.js', function( ) {
FB.init( {
appId : 'xxxxxxxxxxxxx',
xfbml : true,
version : 'v2.0',
} );
window.App.advanceReadiness();
} );
}
});

Related

What to do after getting 'not_authorized' back from Facebook Connect login

After your get your response from getLoginStatus, is the idea to then call FB.login? Currently when I do that, the code stops.
Here's the code for when they hit the FB button to login, which correctly gives me the response...
function facebookConnectBtnLogin()
{
FB.getLoginStatus(function(response)
{
CL();
if (response.status === 'connected') {
logFacebookUserIn(response);
} else if (response.status === 'not_authorized') {
// alert('not_authorized...');
facebookLoginInit();
} else {
//alert('not logged into Facebook...');
facebookLoginInit();
}
},true);
}
And the code that deals with FB.login, which alerts 'here4', but not 'here5'...
function facebookLoginInit()
{
alert('here4');
FB.login
(
function(response)
{
alert('here5');
CL();
if(response.authResponse)
{
alert('here6'); logFacebookUserIn(response);
} else alert('not connected');
},
{ scope: "email" }
);
}
Do I have the right idea?
Thanks for your time and help.
You should never call FB.login in an asynchronous callback function, ONLY on direct user interaction (mouse click). Browsers block the FB.login popup if you don´t call it on user interaction.
With FB.getLoginStatus you just check if the user is authorized, if not: present a Login Button where the user can click to login. It´s not a good idea to show the login dialog right when the user enters your App anyway, tell him what the App is about first.

Empty Facebook popup after login

The first time my users accesses the app, everything works fine. The user gets a popup with the question to authorize my app. But then, the next session(ex. refresh), he gets an empty popup that closes itself in an instant.
I believe it's Facebook asking for a new access token, but the problem is that I don't find it user friendly. When a popup opens and closes itself that fast, the user thinks there's something wrong or that he missed something.
Here's the code:
window.fbAsyncInit = function() {
FB.init({
appId : '', // App ID
channelUrl : '', // Channel File
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
// Here we subscribe to the auth.authResponseChange JavaScript event. This event is fired
// for any authentication related change, such as login, logout or session refresh. This means that
// whenever someone who was previously logged out tries to log in again, the correct case below
// will be handled.
FB.Event.subscribe('auth.authResponseChange', function(response) {
// Here we specify what we do with the response anytime this event occurs.
if (response.status === 'connected') {
// The response object is returned with a status field that lets the app know the current
// login status of the person. In this case, we're handling the situation where they
// have logged in to the app.
if(accessToken)
{
//console.log("Connected WITH accesToken");
testAPI();
}
else{
// console.log("Connected WITHOUTaccesToken");
FB.login(function(response) {
// handle the response
uid = response.authResponse.userID;
accessToken = response.authResponse.accessToken;
//console.log(uid);
//console.log(accessToken);
}, {scope: 'friends_location, user_location, user_relationships'});
}
} else if (response.status === 'not_authorized') {
// In this case, the person is logged into Facebook, but not into the app, so we call
// FB.login() to prompt them to do so.
// In real-life usage, you wouldn't want to immediately prompt someone to login
// like this, for two reasons:
// (1) JavaScript created popup windows are blocked by most browsers unless they
// result from direct interaction from people using the app (such as a mouse click)
// (2) it is a bad experience to be continually prompted to login upon page load.
//alert("You're logged in on FB but not on the APP");
FB.login();
} else {
// In this case, the person is not logged into Facebook, so we call the login()
// function to prompt them to do so. Note that at this stage there is no indication
// of whether they are logged into the app. If they aren't then they'll see the Login
// dialog right after they log in to Facebook.
// The same caveats as above apply to the FB.login() call here.
// FB.login();
//alert("You're offline on FB");
FB.login();
}
});
};
// Load the SDK asynchronously
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
// Here we run a very simple test of the Graph API after login is successful.
// This testAPI() function is only called in those cases.
function testAPI() {
FB.api('/'+uid+'/friends?fields=name,location,picture&accesstoken='+accessToken, function(response) {
}
//<img border="0" src="console.log(response.data[0].picture.data.url)">
}
});
}
//Logout
function fbLogout() {
//FB.init();
FB.logout(function (response) {
//Do what ever you want here when logged out like reloading the page
//window.location.reload();
});
}
How can I prevent this empty popup?
You are explicitly calling FB.login, vs FB.getLoginStatus, which is a wrapper around the login dialog. This is why you always get the popup.
Instead, first call getLoginStatus, and only if this fails, you present a button which triggers login.

User Skips Permission in Facebook Auth Dialogue Javascript SDK

I have an app in a page tab that uses the facebook javascript sdk. When a new user comes to the app, I get the expected "Log in with facebook" pop-up. I also have some extended permissions that I've put in the scope parameter of FB.Login. After the users logs in with facebook I see the expected extended permissions pop-up. The only problem is if the user skips the extended permissions, the dialogue returns back an access_token, but it's not valid for the extended permissions. Code example below.
window.fbAsyncInit = function () {
FB.Canvas.setAutoGrow();
FB.init({
appId: facebookAppId,
status: true, // check login status
});
function updateFBInfo(response) {
console.log('updateResp:');
if (response.authResponse) {
//user is already logged in and connected
FB.api('/me', function (info) {
displayUserInfo(info, response);
});
}
else {
FB.login(function (loginResponse) {
if (loginResponse.authResponse) {
FB.api('/me', function (info) {
displayUserInfo(info, loginResponse);
});
}
}, { scope: 'email,manage_pages,offline_access,publish_stream' });
}
}
FB.getLoginStatus(updateFBInfo);
};
I guess my question is either, what am I missing (this has got to be something easy), or is there a way to check and see if the returned acces_token is actually valid?
You need to check explicitly for the permission before proceeding. If they haven't provided the necessarily permissions, you need to display FB.login() with the necessary scope again.
Here is the code for checking permissions:
FB.api('/me/permissions', function (response) {
var perms = response.data[0];
// Check for publish_stream permission in this case....
if (perms.publish_stream) {
// User has permission
} else {
// User DOESN'T have permission. Perhaps ask for them again with FB.login?
}
} );

Facebook Application - Unable to get inside FB.getLoginStatus and execute something

I'm using the following code:
alert('Inside login status');
FB.getLoginStatus(function (response) {
if (response.status === 'connected') {
//user is logged in and connected
userid = response.authResponse.userID;
accesstoken = response.authResponse.accessToken;
alert('Welcome' + response.authResponse.name);
//return 'connected'
//do something with user
}
else if (response.status === 'not_authorized') {
//user is logged into facebook but not connected to the app
//do something
alert('Like us to get started');
//return 'not_authorized'
}
else {
//the user even connected to facebook
//button.innerHTML = 'unknown'
//button.onclick = function () { login(); }
alert('login to get started');
//login();
//return 'unknown'
}
});
I have defined the above code in a function that is called in the async init. (The async init is defined in the code behind, I'm registering the script to the head of the page on page load) The first alert is called which means I get into the function, but the rest of it doesn't seem to work. No alerts are displayed after that.
On debugging using breakpoints, I was just directed to the end of the function. No clue why this happens. Am I missing something?
Make sure that you have specified correct callback URL in facebook application setting. And If you are testing it on local machine, have you created virtual directory?
It's just the way it runs on my system. I deployed it to a different environment and it worked like a charm.

FB undefined while using getLoginStatus in page show

I am getting FB undefined , when i write following code , i have successfully added the necessary files for facebook using window.fbAsyncInit , the thing is if i write following code under "click" event then it works well but not at the time of pageshow in jquery mobile. this is happening might be because the facebook js files are loading bit late. but i want to check the user status on every page to restrict unnecessary or anonymous access.
$("#details").live( "pageshow", function() {
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
// the user is logged in and connected to your
// app, and response.authResponse supplies
// the user's ID, a valid access token, a signed
// request, and the time the access token
// and signed request each expire
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
console.log("INSIDE ME");
} else if (response.status === 'not_authorized') {
// the user is logged in to Facebook,
//but not connected to the app
console.log("OUTSIDE ME");
} else {
// the user isn't even logged in to Facebook.
}
});
});
Put the jQuery live() assignment inside the window.fbAsyncInit as well. So that way it is only applied to the DOM element after FB has a chance to initialize.