FB.logout() called without an access token - javascript

I'm trying to log out of a website i've created with Facebook integrated.
Logging in works fine, but when I want to log out Firebug consistently gives me this error:
FB.logout() called without an access token.
I'm using the Facebook JavaScript SDK, and the code I've got to logout looks like this:
$(document).ready($(function () {
$("#fblogout").click(facebooklogout);
}));
function facebooklogout() {
FB.logout(function (response) {
}
)};
This is the logout code specified at the Facebook Developers Documentation just with a button being assigned the method on document.ready
Before this code I have the FB.init() method, that all runs fine.
If anyone's got a solution as to why FB.logout doesn't have an access token, it'd be appreciated.

To logout from the application which uses facebook graph API, use this JavaScript on the logout page just after the <form> tag:
window.onload=function()
{
// initialize the library with your Facebook API key
FB.init({ apiKey: 'b65c1efa72f570xxxxxxxxxxxxxxxxx' });
//Fetch the status so that we can log out.
//You must have the login status before you can logout,
//and if you authenticated via oAuth (server side), this is necessary.
//If you logged in via the JavaScript SDK, you can simply call FB.logout()
//once the login status is fetched, call handleSessionResponse
FB.getLoginStatus(handleSessionResponse);
}
//handle a session response from any of the auth related calls
function handleSessionResponse(response) {
//if we dont have a session (which means the user has been logged out, redirect the user)
if (!response.session) {
window.location = "/mysite/Login.aspx";
return;
}
//if we do have a non-null response.session, call FB.logout(),
//the JS method will log the user out of Facebook and remove any authorization cookies
FB.logout(handleSessionResponse);
}
The code works and is live on my site.

I went for the less trivial solution:
function facebookLogout(){
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
FB.logout(function(response) {
// this part just clears the $_SESSION var
// replace with your own code
$.post("/logout").done(function() {
$('#status').html('<p>Logged out.</p>');
});
});
}
});
}

Figured it out after so many tries.
Generally response.authResponse.accessToken contains token. So, its error about the accessToken not being there.
Think logically, where does that response come from in your code? Out of nowhere.
So, we need to get that response object from a function and get this working.
I don't know how it worked for others, but this worked for me.
Just replace the code with this
function logout(){
FB.getLoginStatus(function(response) {
FB.logout(function(response){
console.log("Logged Out!");
window.location = "/";
});
});
}
What we do here is, get the login status if the user is logged in and get the corresponding response in return, which contains all the necessary tokens and data. Once this is fetched, the token is used to log out the user.

I've tried something like this:
function fbLogout(){
if(typeof FB.logout == 'function'){
if (FB.getAuthResponse()) {
FB.logout(function(response) { window.location.href = PROJECT_PATH + '/index/logout'; });
return;
}
};
window.location.href = PROJECT_PATH + '/index/logout';
return;
}

Should be something more like this. There was a change to the JS API where you have to use authResponse instead of just session.
//handle a session response from any of the auth related calls
function handleSessionResponse(response) {
//if we dont have a session (which means the user has been logged out, redirect the user)
if (!response.authResponse) {
return;
}
//if we do have a non-null response.session, call FB.logout(),
//the JS method will log the user out of Facebook and remove any authorization cookies
FB.logout(response.authResponse);
}

The error says that you don't have an access token, you have to check for one using the FB.getAccessToken() function.
If there is no access token the function returns null. See example below:
function facebooklogout() {
try {
if (FB.getAccessToken() != null) {
FB.logout(function(response) {
// user is now logged out from facebook do your post request or just redirect
window.location.replace(href);
});
} else {
// user is not logged in with facebook, maybe with something else
window.location.replace(href);
}
} catch (err) {
// any errors just logout
window.location.replace(href);
}
}

With Typescript this function do work fine ..
signOutFacebook(): void {
/*SIGN OUT USER FACEBOOK.*/
FB.getLoginStatus(function (response) {
if (response.status === 'connected') {
FB.logout(function (response) {
console.log("Logged Out!");
});
} else {
console.log("The person is not logged into your webpage or we are unable to tell. !");
}
});
}/*FINAL 'signOutFacebook()'. */

Related

yam.platform.getLoginStatus invokes callback without response.user

When I call yam.platform.getLoginStatus right after logging in using yam.platform.login (shows the popup etc.) I get a different object passed to the callback than when the user is already logged in. Specifically, the 'user' field is missing on the LoginStatus response object, otherwise it looks the same as far as I can see.
I have the following controller for a 'login with yammer' area on my angular app:
function YammerLoginController($scope, $compile) {
$scope.isLoggedIn = false;
$scope.userName = "-";
$scope.login = function () {
yam.platform.login(function (response) {
if (response.authResponse) {
console.log("logged in");
}
refreshLoginStatus();
});
}
refreshLoginStatus(); // initialize values
function refreshLoginStatus() {
yam.getLoginStatus(function (response) {
console.dir(response);
if (response.authResponse) {
if (response.user) {
console.log("YammerLogin: Logged in as " + response.user.full_name);
console.dir(response);
$scope.$apply(function () {
$scope.isLoggedIn = true;
$scope.userName = response.user.full_name;
});
}
else {
console.log("WTF Yammer API!"); // THIS HAPPENS.
}
}
else {
console.log("YammerLogin: Not logged in.");
$('#loggedInView').popover("hide");
$scope.$apply(function () {
$scope.isLoggedIn = false;
$scope.userName = "-";
});
}
});
}
When the controller is created it already queries the current login status using the refreshLoginStatus function. If a yammer user is already logged in the app will display the user name and a logout button on the page (done with ng-show="isLoggedIn"). If the user is not logged in, a login button will be shown instead. When the user clicks on that login button, the $scope.login function will be called, invoking yam.platform.login and, if successful, calls refreshLoginStatus again in order to retrieve and set the user's name. In this scenario, the object returned from both, login and getLoginStatus do not contain the user information like in the 'user is already logged in' scenario. I tried calling the SDK-API again after some timeout, but apparently the response is cached - I always get the same. Only refreshing the whole page clears out the current response, querying the status again and receiving a 'complete' response object.
I thought it could be a scoping problem, but by now I'm not sure whether it's a problem in the SDK itself. :S
EDIT: I kind of found a solution, which however only gives me worse problems. Apparently the request is indeed cached. A refresh can be forced by using 'force refresh' on yam.platform.getLoginStatus(callback, [forceRefresh]). This, however gives me the following error on the browser console:
XMLHttpRequest cannot load
https://www.yammer.com/platform/login_status.json?client_id=2h4U2Hndg5kdWQ8xxxxxx.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:9000' is therefore not allowed
access.
Basically, the SDK fails to getLoginStatus, completely, and reports this back to my code as 'no connection'. I'm not sure what's worse... or, what am I doing wrong?
It appears that is just an inconsistency in the yam.platform.getLoginStatus API or the corresponding Yammer service called. If the user logs in, you get the user info, if he is alreaddy logged in, you don't get it. That is just weird but apparently can't be helped.
However, I solved this problem by simply always getting the user login data using a separate REST service call on /users/current.json once the session is authenticated (once I have the token from getLoginStatus).

Facebook SDK for Javascript, FB.login() callback not firing (async call never gets a response?)

The below code is my Facebook API javascript so far. It's pretty simple, with a bunch of console.log()s to follow the code flow. (I recognize that naming arguments response and response2 is terrible practice but it's just what I put quickly for now to avoid naming conflicts).
As it stands, FB.init() succeeds, FB.getLoginStatus() works, and the two FB.api() calls work, but FB.login() never happens. It is async though so the console.log()s just before and just after do execute. To summarize, my console output is:
makes it here
makes it here too
Permissions:
Object {data: Array[37]}
Good to see you, my-name-is-here.
I guess it's because the async FB.login() call never gets a response so the callback never fires, thus no console.log()s from inside the function. But I need this FB.login() in order to get extended permission ads_management. Any idea what is wrong, or at least a direction to go about solving this myself?
window.fbAsyncInit = function() {
FB.init({
appId: 'my-app-id-is-here',
xfbml: true,
version: 'v2.0'
});
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
FB.api('/me', function(response2) {
console.log("Good to see you, " + response2.name + ".");
});
FB.api('/me/permissions', function(response2) {
console.log("Permissions:");
console.log(response2);
});
console.log("makes it here");
FB.login(function(response2) {
console.log("why not here?");
if (response2.authResponse) {
console.log("Response to login asking for ads_management permission");
console.log(response2);
} else {
console.log("User cancelled login or did not fully authorize.");
}
}, {
scope: 'ads_management',
return_scopes: true
});
console.log("makes it here too");
} else {
// filled with other code that doesn't effect this question yet
}
});
};
UPDATE:
Taking away the parameters argument {scope: 'ads_management', return_scopes: true} makes the FB.login() call at least be attempted, but in the console there is now the error:
"FB.login() called when user is already connected."
but I thought the way to get more permissions when the user is already logged in IS by calling FB.login() again, with the desired permissions specified in the parameters argument.
Your flow is not correct. First check for the permission in the FB.api("/me/permissions") callback (since the facebook api calls are asynchronous), and then if that particular permission is not yet granted, then call FB.login().
Here you go-
if (response.status === 'connected'){
FB.api('/me/permissions', function(response){
var hasPermission = false;
var response = new Array();
response = response.data;
response.map(function (data) {
if (data.permission == "ads_management" && "status" == "granted") {
hasPermission = true;
}
});
if(!hasPermission)
// call FB.login() here
});
}
Try to use oauth:true in your FB.init.
And you should check by code if you don't already have needed permission before issuing FB.login.

FB.getLoginStatus doesn't work in Chrome even sandbox disable

I follow railscast to add "sign in with Facebook" feature in my site, there is no problem to login. But when try to logout, it seems that FB.getLoginStatus never got fire even when I disable Sandbox Mode in facebook developer app settings (as suggested in some other discussion):
(function() {
jQuery(function() {
$('body').prepend('<div id="fb-root"></div>');
return $.ajax({
url: "" + window.location.protocol + "//connect.facebook.net/en_US/all.js",
dataType: 'script',
cache: true
});
});
window.fbAsyncInit = function() {
FB.init({
appId: 'xxxxxomittedxxxxx',
cookie: true,
status: true,
xfbml: true,
oauth: true
});
$('#sign_in').click(function(e) {
e.preventDefault();
return FB.login(function(response) {
if (response.authResponse) {
return window.location = '/auth/facebook/callback';
}
});
});
return $('#sign_out').click(function(e) {
FB.getLoginStatus(function(response) {
if (response.authResponse) {
return FB.logout(response.authResponse);
}
});
return true;
});
};
}).call(this);
The reason I know the FB.getLoginStatus never get in (or doesn't work) is I replace the body with:
FB.getLoginStatus(function(response) {
return alert("I am here!");
});
and I cannot see my alert while "sign_out" click.
I am running both Chrome and Firefox having the same behaviour. Could anybody help to spot what am I missing? Thanks a lot.
Let me describe more specific about the "behaviour" I encountered:
sign in with Facebook from mysite.com the first time a Facebook login window will popup and ask for email and password, and I can sign in to my site perfectly ok and work as expected
then I click on sign_out button from mysite.com/users/1, it looks like it sign out ok.
then sign in with Facebook from mysite.com again, now it won't popup the Facebook login window anymore and login to mysite.com/users/1 directly without asking email and password!
if I open another browser window and go to facebook.com and logout from there, then when I sign in with Facebook from mysite.com, it will popup a Facebook login window now and ask for my email and password.
I would like my site to behave: "when logout from mysite.com/users/n and sign in with Facebook again from mysite.com, the Facebook login window shall popup"
Anyone could be of help? Thanks a lot.
EDIT:
Further investigation found the "root" cause might be still: the sign out is under the different route (or page) of the sign in route and FB.getLoginStatus just cannot be fire under the mysite.com/signout. The error message from firebug indicates that "Given URL is not allowed by the Application configuration.: One or more of the given URLs is not allowed by the App's settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App's domains."
To proof it is the route issue, I put a sign out link in the same route (page) as sign in route which is the root route mysite.com as specified in the "Website with Facebook Login", everything works and can logout as expected:
<%= link_to "sign out facebook", "#" , id: "sign_out" %>
by the way the sign_out js is revised to get rid of FB.logout(response.authResponse) uncaught [object Object] error, because FB.logout expects function as parameter:
return $('#sign_out').click(function(e) {
FB.getLoginStatus(function(response) {
if (response.authResponse) {
FB.logout();
}
}, true);
});
};
So, the bottom line: FB.getLoginStatus might still have a bug which cannot handle the call from a different route than sign in route. (I tested with Chrome, Firefox and Safari and all behave the same but not true for IE10. Somehow IE10 works even sign out at different route.)
Any comment from people who have similar problem? Please advise. Thank you very much in advance.
Try adding true as second parameter to getLoginStatus, as stated in FB dev doc:
FB.getLoginStatus(function(response) {
// this will be called when the roundtrip to Facebook has completed
}, true);
This should avoid caching.
Another option is to subscribe to events:
FB.Event.subscribe('auth.login', function(response) {
// do something with response
});
All from here
Comment if you have questions.
EDIT:
I modified your script a little bit, removed unneeded code parts. You had too many returns that are not needed. I tried sign out within this modified script, it works as you need it.
Events subscription is for check purposes.
<head>
<title>Exam entry</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
</head>
<body>
<div id="fb-root"></div>
<input type="button" value="Sign in" id="sign_in" />
<input type="button" value="Sign out" id="sign_out" />
<script type="text/javascript">
window.fbAsyncInit = function () {
FB.init({
appId: '586844044669652',
cookie: true,
status: true,
xfbml: true
});
// 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.
testAPI();
} /*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.
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();
}*/
});
$('#sign_in').click(function (e) {
e.preventDefault();
FB.login(function (response) {
if (response.authResponse) {
//return window.location = '/auth/facebook/callback';
}
});
});
$('#sign_out').click(function (e) {
FB.logout(function (response) {
console.log("Here logout response", response);
});
});
};
// 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() {
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function (response) {
console.log('Good to see you, ' + response.name + '.');
});
}
// 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));
</script>
</body>

FB.getLoginStatus not working if user is inactive

In my Canvas App (tab page) I use this code to get the AccessToken if the app needs it:
var accessToken = "";
FB.getLoginStatus(function (response) {
if (response.authResponse || response.status === 'connected') {
accessToken = response.authResponse.accessToken;
}else {
alert( response.status );
}
} );
return accessToken;
I works fine. BUT if user opens the app and leave it for about 30minutes (or less or more, just for a long time) after this functions can't get the accessToken just return with an empty string. In the console log there aren't any error. After if the user refresh the page everything is fine...
What should I do to can get the accessToken anytime?
Here's what's going on:
The FB.getLoginStatus method is done asynchronously, and you give it a callback to execute once finished.
In your code you return the accessToken right after issuing the async request, but you're not waiting for it to be completed.
It should look like:
FB.getLoginStatus(function (response) {
if (response.authResponse || response.status === 'connected') {
return response.authResponse.accessToken;
} else {
alert( response.status );
}
});
So you might ask yourself "so why does it work to begin with?", the answer is simple: at first the sdk has the authentication data and does not need to actually make the request to the fb servers, as it states in the documentation of the method:
Roundtrips to Facebook's servers
To improve the performace of your application, not every call to check
the status of the user will result in request to Facebook's servers.
Where possible, the response is cached. The first time in the current
browser session that FB.getLoginStatus is called, or the JD SDK is
init'd with status: true, the response object will be cached by the
SDK. Subsequent calls to FB.getLoginStatus will return data from this
cached response.
If you try your code with passing `true', like this:
var accessToken = "";
FB.getLoginStatus(function (response) {
if (response.authResponse || response.status === 'connected') {
accessToken = response.authResponse.accessToken;
} else {
alert( response.status );
}
}, true);
return accessToken;
Then it should not work at all.
Call FB.login in such a case, that just opens the popup and immediately closes it again, if the user is still logged into FB and you don’t request any new permissions.

Facebook permissions in IE Causing infinite facebook loop

I am trying to get permissions for a facebook app I am making, but every time I try to run the app in IE8 I cannot get the permissions box to show up. I have tested the app in firefox and it can open fine, and get all the permissions fine (i dont ask for any special ones).
When I run the debugger in IE8 I see that once the program hits FB.getLoginStatus(function (response) { (see code below) it then moves into an infinite loop of code written by facebook.
I think the issue is because of how I am making the permissions call. I have a form that I use for a login that will call the permissions method once the user attempts to login to the site. Here is the form and button in the form I use:
<form id = "membershipInfo" method = "post" action = "Login.aspx">
<input type = "button" id = "submitInfo" class = "MemberInfo" value = "Take Me There!" onclick = "authorize(acceptPermissions, rejectPermissions)"/>
And here is the auth method I use:
function authorize(successCallback, failureCallback) {
FB.getLoginStatus(function (response) {
//****** DOES NOT MAKE IT PAST HERE *******//
if (response.session) {
// logged in and connected user, carry on
session = response.session;
//Set access token
accessToken = response.session.access_token;
//Call success callback
successCallback();
} else {
// no user session available, Lets ask for perms
FB.ui(
{
method: 'permissions.request',
perms: permissionString //(equals "" )
},
function (response) {
if (response && response.session != null) {
//Get session
session = response.session;
//Set access token
accessToken = response.session.access_token;
//Call success callback
successCallback();
} else {
//Call failure callback
failureCallback();
}
});
}
});
When the user accepts permissions they get moved into a success callback method which is here (never makes it this far):
function acceptPermissions() {
//Code done before moving on
$('#submitInfo').submit();
}
Anyone see any issues?
That looks like it should work to me, so probably a good opportunity to file a bug report with Facebook....
That said, I think you could clean up your code using FB.login instead http://developers.facebook.com/docs/reference/javascript/FB.login/
FB.login(function(response){
if(response.session){
// logged in and connected user, carry on
session = response.session;
//Set access token
accessToken = response.session.access_token;
//Call success callback
successCallback();
}
else{
failureCallback();
}
}, {perms: permissionString});
So here's a question: do you have Flash installed? IE8, being the way it is, may be trying to load the Flash-based XD, and then failing silently. If you install Flash (and/or put in a catch for that), does it work?

Categories