Meteor: Facebook basic API call error: access token - javascript

I am currently trying to make a simple API call to show some user data (including a friends list).
I have a working Facebook login with the following request permission (
'click .facebook': function() {
Meteor.loginWithFacebook({ requestPermissions: ['email', 'read_friendlists', 'accesToken']},
function (error) {
if (error) {
return console.log(error);
}
});
},
Than I initialize facebok through
Template.friendsList.rendered = function(){
window.fbAsyncInit = function() {
FB.init({
appId : '278237565717322',
xfbml : true,
version : 'v2.0'
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
And I want to make a simple API call with
"click .facebookfriends": function(){
FB.api('/me', function(response) {
console.log(response)
});
}
This gives me the following error:
code: 2500
message: "An active access token must be used to query information about the current user."
type: "OAuthException"
I have tried several examples but cannot seem to find a way to do loginWithFacebook and get the proper accesstoken. Could anyone help me with getting a proper access token set up? Much appreciated!

It looks like you are mixing the Meteor package Facebook OAuth login flow with Facebook's own JS SDK. Whenever I did stuff with FB on Meteor I avoided the JS SDK and opted purely for the Meteor package. Regardless it seems your problem is that you are getting the access token via the meteor package but the the FB JS SDK has no access to it when you call FB.api({ ... })
Try something like:
server:
Meteor.methods({
fb_me: function() {
var user = Meteor.users.findOne(this.userId);
//note: I don't have access to a meteor project hooked up to the FB API
//so where the access token is stored in a user object may differ,
//I got this from an old project. Try logging user here to find it
//if this doesn't work
var accessToken = user.services.facebook.accessToken;
if (!user || !accessToken)
throw new Meteor.Error(500, "Not a valid Facebook user logged in");
return HTTP.get("https://graph.facebook.com/me", {
params: {access_token: accessToken}}).data;
}
});
client:
"click .facebookfriends": function(){
Meteor.call('fb_me', function(err, res) {
if (!err)
console.log(res);
}
}
That works without having to use the FB JS SDK at all.
Since it's likely you would be letting your client make a lot of API calls I would suggest you make a single Meteor.method that takes a API endpoint (e.g. /me) as an argument and returns data to the client similar to the FB.api method Facebook provide.

Related

Reading a Facebook personal page posts

I'm working on a feature on our website to display my company's Facebook page posts on our Intranet site. I found this code and am having trouble.
<script>
window.fbAsyncInit = function() {
FB.init({
appId : '<ourappid',
xfbml : true,
version : 'v2.8'
});
FB.AppEvents.logPageView();
FB.login(function (response) {
if (response.authResponse) {
//alert("You are logged in");
FB.api('/ourpageurl/feed', function(response) {
console.log("response",response);
})
} else {
alert("Login attempt failed!");
}
}, { scope: 'public_profile' });
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
I do not control our company's Facebook page. Our social media director provided me with the app id. When I run the code above on a browser where I have not logged into Facebook with my username, I get a pop up window asking for my Facebook credentials. When I run this on a browser where I have an active Facebook session, the code does nothing. Nothing inside the login callback function is executed.
I've also tried skipping the FB.login portion and just running
FB.api('/ourpageurl/feed', function(response) {
console.log("response",response);
})
immediately after FB.AppEvents.logPageView();, but I get an error object back complaining about an access token. As far as I've been able to tell, in order to get an access token, I have to run the login method. What am I doing wrong here?
First of all: You can only call FB.login on user interaction, or browsers will block the popup. If done correctly, FB.login opens a popup where you can authorize the App with your user account.
I assume that is not what you want. For getting the feed of an unrestricted Page, you can use an App Access Token - it is the only Token that does not need user authorization. Access Tokens are meant to be kept secret, so you need to do that API call on your server, NOT on the client with JavaScript. You also need to think about caching the result, if a lot of users hit the Page where you read/show the feed, you may hit an API limit on Facebook.
About Tokens in general:
https://developers.facebook.com/docs/facebook-login/access-tokens/
http://www.devils-heaven.com/facebook-access-tokens/

Error in the response from facebook graph API

My code till now is this:
<script>
window.fbAsyncInit = function(){
FB.init({ appId:'my app id', status:true, cookie:true, xfbml:true});
FB.getLoginStatus(function(response){
if (response.status != "unknown") // makes sure the user is already logged in.
{
FB.api('/me', function(response) {
console.log(response);
});
}
});
};
// Load the SDK Asynchronously
(function(d){
var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
d.getElementsByTagName('head')[0].appendChild(js);
}(document));
</script>
The error that I'm getting in the console is "An active access token must be used to query information about the current user."
But I have already made sure that the user is logged in as seen from the code, then where am I making a mistake?
Update: From the answers and the comments, it seems like the problem is that my website is not authorized although the user is logged in.
I just want to display the user's real name on the website with a welcome message. Can I use facebook graph API for this?
I do not want to go into authorization step since that would seem unnecessary from the user's point of view.
I'm new to programming, javascript and facebook graph api, so please forgive any mistakes I might have made.
Where did you make sure the user is logged in? You did not authorize the user anywhere, you only checked if he is logged in. For example:
FB.login(function(response) {
if (response.authResponse) {
//user just authorized your app
}
}, {scope: 'email,public_profile'});
You may want to use getLoginStatus correctly too:
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
//user is authorized
} else {
//user is not authorized
}
});
Source: http://www.devils-heaven.com/facebook-javascript-sdk-login/

Facebook Javascript API call returns error requiring appsecret_proof argument - but this is client side

I'm using Facebook's Javascript SDK, but it's returning the error:
API calls from the server require an appsecret_proof argument
I'm familiar with why it would return this error server-side through PHP - but this is client-side javascript, and can't see why it would ever return this error.
Stripped-down code as follows:
window.fbAsyncInit = function () {
FB.init({
appId: [my app id],
xfbml: true,
version: 'v2.2'
});
};
(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement(s);
js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
FB.login(function (res) {
if (res.authResponse) {
if (res.authResponse.grantedScopes.indexOf("manage_pages") >= 0) {
FB.api('/me/accounts', function (res) {
if (res && !res.error) {
/*
* Should show pages available for
* the facebook user to manage ...
* (code removed)
*/
}
else {
/*
* Instead, shows 'API calls from the
* server require an appsecret_proof
* argument" error here
*/
console.log("Error /me/accounts: " + JSON.stringify(res.error));
}
});
}
}
});
This works fine if I turn off the 'App Secret Proof for Server API calls' in the Facebook App settings, but for security reasons I want this on.
This shouldn't fail through a javascript call - it's a client-side API call, not a server API call that the error message describes it as.
Is this a bug with Facebook, or something I'm missing somewhere?
As of February 2018, the issue (or a very similar one) seems to have reappeared. There's a bug report for this:
https://developers.facebook.com/bugs/1597942793626594/
That is, for an application with Require App Secret enabled, it seems that one cannot perform API calls from Javascript without passing the appsecret_proof - at the moment of writing.
Other notes:
Excerpt from docs:
When this is enabled, we will only allow API calls that either include
appsecret_proof or are made from the same device the token was issued
to.
However, in the application Settings > Advanced > Security > Require App Secret the description is as follows:
Only allow calls from a server and require app secret or app secret
proof for all API calls.
Related bug reports: October 2016, February 2015.
Related SO post: API calls from the server require an appsecret_proof argument.

Retrieve feed from facebook - sdk 4.0

I've been trying to retrieve someone's facebook feed using both php and javascript but nothing has worked so far. According to what I've tried, a session is needed to retrieve an access token and therefore be able to see someone else's publicly feed - developers.facebook.com/docs/facebook-login/access-tokens/#usertokens
If we try the following url: graph.facebook.com/PAGE-ID/feed it returns an error saying that An access token is required to request this resource.
Below's my javascript attempt, based on the facebook sdk documentation:
http://pastebin.com/2KkU0iyF
window.fbAsyncInit = function() {
FB.init
({
appId : 'APP-ID',
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true, // parse XFBML
version: 'v2.2'
});
FB.Event.subscribe('auth.login', function()
{
window.location.reload();
});
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
console.log('Logged in.');
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
if(typeof facebookInit !== 'undefined')
facebookInit();
}
else {
FB.login(function (response) {
if (response.authResponse) {
// some code here
} else {
alert("Login attempt failed!");
}
} //, { scope: 'read_stream' } // do I need to use scope here?
);;
}
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
function facebookInit() {
FB.api('/PAGE-ID/feed', function(response) {
console.log(response); // the returned array is empty
});
}
Thing is, the /PAGE-ID/feed is returning an empty array. I've tried to ask for something like /me and it prints basic information in the console, like name, id, username and so on.
Console output:
Objectdata: Array[0]
__proto__: Object
I believe I'm missing something simple like permissions or so (I tried to use scope in the login phase). However, according to the Graph API documentation (developers.facebook.com/docs/graph-api/reference/v2.2/post/),
any valid access token should work if the post is public.
PHP attempt: http://pastebin.com/4wCBqSTu
session_start();
define('__ROOT__', dirname(dirname(dirname(__FILE__))));
require (__ROOT__.'/resources/facebook-php-sdk-v4-4.0-dev/autoload.php');
// added in v4.0.5
use Facebook\FacebookHttpable;
use Facebook\FacebookCurl;
use Facebook\FacebookCurlHttpClient;
// added in v4.0.0
use Facebook\FacebookSession;
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookRequest;
use Facebook\FacebookResponse;
use Facebook\FacebookSDKException;
use Facebook\FacebookRequestException;
use Facebook\FacebookOtherException;
use Facebook\FacebookAuthorizationException;
use Facebook\GraphObject;
use Facebook\GraphSessionInfo;
use Facebook\GraphUser;
// init app with app id and secret
FacebookSession::setDefaultApplication('APP-ID','APP-SECRET');
// get app access_token
$session = FacebookSession::newAppSession();
// make request to Facebook
$request = new FacebookRequest( $session, 'GET', '/PAGE-ID/feed' ); // /PAGE-ID only would retrieve the basic info, like username
$response = $request->execute();
// get response as array
$content = $response->getGraphObject();
print_r($content);
// output html
?>
First things first. Do I really need to ask for login here? I only want to read the public posts. Isn't app-id and app-secret enough to generate the session?
According to the documentation, the /feed returns an array of post objects.
However, when I use /PAGE-ID/feed the return is an empty array: [backingData:protected] => Array ( )
If I use /PAGE-ID only, it prints the basic information, such as username, name, etc..
Any suggestions?
Edit
Working examples:
pastebin.com/8WzmzxX0
pastebin.com/wKcfB8vj
Thanks
Even for public posts, you MUST use a User Token for the specific User, and you need to authorize him with the read_stream permission.
That being said, you may want to read this:
This permission is granted to apps building a Facebook-branded client on platforms where Facebook is not already available. For example, Android and iOS apps will not be approved for this permission. In addition, Web, Desktop and TV apps will not be granted this permission.
Source: https://developers.facebook.com/docs/facebook-login/permissions/v2.2
That is for User profiles. If you want to retrieve a Page feed, you can even use an App Token without authorization, unless the Page is restricted (country, age) - in that case you need to use a User Token or Page Token. More information about Access Tokens:
https://developers.facebook.com/docs/facebook-login/access-tokens/
http://www.devils-heaven.com/facebook-access-tokens/

Facebook access token changes on every pageload

is it correct that the Facebook API access token changes on every pageload?
I thought once a token was obtained, it would stay the same until expiry.
I am using the Facebook SDK for Javascript.
Facebook says that with this SDK, there is no need to manually manage access tokens. The SDK just does it.
But is it correct that the token changes on every pageload?
My code is this:
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : 'xxxxxxxx',
status : true,
xfbml : false,
cookie : true
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
function check() {
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
console.log(response);
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
console.log(response);
} else {
// the user isn't logged in to Facebook.
console.log(response);
}
});
}
</script>
<span onClick="check()">test</span>
I just tested this and you are right, the Token changes with every page refresh. I would not worry much about it though, when using one of the SDKs (JavaScript, PHP, ...) you most likely don´t need to think about the Access Tokens at all.
And even if you need them (for managing Pages, for example), you can just use the last one.
The "older" Tokens are still valid btw, they don´t get invalidated. But they will stop working after 2 hours anyway.
There is also a second parameter you can set to "true": https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/ (see "Roundtrips to Facebook's servers") - which may have explained the new Token, but you´re not using that either.
Facebook has recently changed its process of refreshing access token.
Try to use this if it works in you case:
https://graph.facebook.com/oauth/access_token?
client_id=APP_ID&
client_secret=APP_SECRET&
grant_type=fb_exchange_token&
fb_exchange_token=EXISTING_ACCESS_TOKEN
EDIT:
This will might help you as well. Link

Categories