Facebook permissions in IE Causing infinite facebook loop - javascript

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?

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).

Retrieving Temporary Access Token using jQuery OAUTH

I am attempting to make an API OAUTH2 call to Shopify to authenticate. When I go to my application, the first screen comes up. I press Install, and then it redirects me back to where I started. The problem is that when I get redirected, I cannnot seem to catch it in my jQuery ajax function and therefore I am unable to get the temporary token I need to create my permanent token from OAUTH. The 2nd image shows what is happening after I press install. My code so far is posed below. None of the console.log() functions are being called after I run the ajax call.
My application URL for my app is set to
http://localhost
and my application is running from
http://localhost/shippingcalculator.
I tested the calls in an external REST client program, and I managed to successfully get my access token, so it is not a problem with my credentials.
<!DOCTYPE html>
<script type="text/javascript">
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
console.log(window.location.search);
var results = regex.exec(window.location.search);
if (results == null) return "";
else return decodeURIComponent(results[1].replace(/\+/g, " "));
}
function getTemporaryToken(token) {
jso_configure({
"shopify": {
client_id: "67d7af798dd0a42e731af51ffa", //This is your API Key for your App
//redirect_uri: "", OPTIONAL - The URL that the merchant will be sent to once authentication is complete. Must be the same host as the Return URL specified in the application settings
authorization: "https://emard-ratke3131.myshopify.com/admin/oauth/authorize",
//In your case the authorization would be https://SHOP_NAME.myshopify.com/admin/oauth/authorize
scope: ["read_products"], //Set the scope to whatever you want to access from the API. Full list here: http://api.shopify.com/authentication.html
}
});
$.oajax({
url: "https://emard-ratke3131.myshopify.com/admin/oauth/authorize",
jso_provider: "shopify",
jso_scopes: ["read_products"],
jso_allowia: true,
success: function(data) {
//Use data and exchange temporary token for permanent one
if (jqXHR.status === 200) {
console.log("200");
}
if (jqXHR.status === 302) {
console.log("300");
}
console.log("Response (shopify):");
console.log(data);
},
error: function(e) {
console.log("Fail GET Request");
console.log(e);
},
complete: function(xmlHttp) {
// xmlHttp is a XMLHttpRquest object
console.log(xmlHttp.status);
}
});
console.log("Code: " + getParameterByName("code"));
}
}
$(document).ready(function() {
getTemporaryToken();
});
</script>
</head>
<body>
Hello World!
</body>
</html>
It's a pretty bad idea to do all of this client side, your API key will be in the clear for anyone to see and use. On top of that where will you store the token? There are also cross site scripting restrictions built into all browsers that will prevent JavaScript from making calls to sites other than the one the js is loaded from.
You should really do the authentication and make all your API calls from a server.

Auto Login Facebook User After Accepting Permissions

I'm trying to login users automatically into my site who have already allowed our facebook app, initially I was going to use :
var cb = function(response) {
if (response.status === 'connected') {
FB.api('/me', function(response) {
$.post( url, { 'op':'facebook','name':response['name'],'id':response['id'],'email':response['email']},
function( data ) {
parent.location.reload();
});
});
} else {
alert('You are not logged in');
}
};
FB.login(cb, { scope: 'publish_actions,publish_stream,read_stream,email' });
Although using that it opens a facebook popup, blocked by many popup blockers and browsers when done in an automatic manner like this and will also display for users who have no allowed our app.
I want it to be done descretely but I'm not sure how :S
If anyone could show me how to log them in using javascript that would be great :)
Prompting a user to login should be hinged off of a user generated event, like clicking on an element. Most browsers will block attempts to automatically open new windows unless there is enough confidence that the user has requested the action.
If you want to automatically detect a visitor's login status when they load your page, you should hook onto the various auth events exposed by the Javascript SDK ("auth.authResponseChange", "auth.login", etc), or manually request the visitor's status using the "FB.getLoginStatus" method. You can read more about these events at https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/
Managed to get it working! Read the facebook tutorial again and this is what I came up with
window.onload=function(){
var url = "http://mysite.com/";
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
FB.api('/me', function(response) {
$.post( url, { 'op':'facebook','name':response['name'],'id':response['id'],'email':response['email']},
function( data ) {
parent.location.reload();
});
});
}
});
};

FB.logout() called without an access token

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()'. */

Should I handle CODE using Javascript SDK FB.login POP-UP or is it handled automatically to gain the access_token?

In the authentication flow documentation here it mentions the CODE which is returned upon oAuth authentication.
Is this required for the Javascript SDK or is this handled automatically in the background in this code?
By "is this required?" I mean, do I have to handle this code to verify the authenticity of the request, or does the JavaScript SDK use the code automatically to gain the access_token.
The documentation explains the client side flow, and how to get the access token using the 'code' so until now. I've been assuming that the SDK manages this automatically in the background, because it produces an access code as response.authResponse.accessToken.
FB.login(function(response) {
if (response.authResponse) {
// User is logged in to Facebook and accepted permissions
// Assign the variables required
var access_token = response.authResponse.accessToken;
var fb_uid = response.authResponse.userID;
alert(dump(response.authResponse));
// Construct data string to pass to create temporary session using PHP
var fbDataString = "uid=" + fb_uid + "&access_token=" + access_token;
// Call doLogin.php to log the user in
$.ajax({
type: "POST",
url: "ajax/doLogin.php",
data: fbDataString,
dataType: "json",
success: function(data) {
// Get JSON response
if (data.result == "failure")
{
alert(data.error_message);
window.location.reload();
return false;
}
else if (data.result == "success")
{
window.location.reload();
return true;
}
},
error: function() {
return false;
}
});
} else {
// user is not logged in and did not accept any permissions
return false;
}
}, {scope:'publish_stream,email'});
I would like to know, because I want to ensure that my code is secure.
From the documentation
With this code in hand, you can proceed to the next step, app authentication, to gain the access token you need to make API calls.
In order to authenticate your app, you must pass the authorization code and your app secret to the Graph API token endpoint at https://graph.facebook.com/oauth/access_token. The app secret is available from the Developer App and should not be shared with anyone or embedded in any code that you will distribute (you should use the client-side flow for these scenarios).
If you plan on using the FB.api function to make calls to their Graph API, then you need the code to get the access token. But if you only need to authenticate the user, then what you have will do that just fine.

Categories