How to access a secret group's posts using facebook-api? - facebook

I am a part of a secret group. I want to get all of the posts and their metadata. I use the following code:
import facebook
if __name__ == '__main__':
APP_SECRET = ""
APP_ID = ""
PAGE_ID = "" ## Page ID of the secret group
access_token = facebook.get_app_access_token(APP_ID, APP_SECRET)
graph = facebook.GraphAPI(access_token)
resp = graph.get_object('me/accounts')
page_access_token = None
for page in resp['data']:
if page['id'] == PAGE_ID:
page_access_token = page['access_token']
graph = facebook.GraphAPI(page_access_token)
but I get this error:
facebook.GraphAPIError: An active access token must be used to query information about the current user.
on line resp = graph.get_object('me/accounts').
Where am I going wrong?

The error message means that you did not authorize the user. How to do that: https://developers.facebook.com/docs/facebook-login/
/me/accounts is the endpoint to get access to pages, for groups you need the user_managed_groups permission and the /me/groups endpoint. You need to use an active User Token for that, of course.
More information: https://developers.facebook.com/docs/graph-api/reference/v2.4/user/groups

Related

facebook api graph not search users

I'm trying to find users but it throws me an authentication error
import requests
from urllib.parse import urlencode
token = 'my-token'
graph_url = 'https://graph.facebook.com/v3.2/search?'
params = {
'q':'francisco',
'type':'user',
'method':'get',
'format':'json',
'access_token':token
}
url = graph_url+urlencode(params)
resp = requests.get(url)
print(resp.json())
error:
{'error': {'message': 'Unsupported operation', 'type': 'OAuthException', 'code': 100, 'fbtrace_id': 'Dao1UbelGkF'}}
It seems that something I'm not doing well or that searches are no longer allowed
https://developers.facebook.com/docs/graph-api/changelog/breaking-changes#search-4-4
Searching for users is not available anymore since 2018. It would not make any sense anyway, you would only be able to get users who authorized your App.

Insufficient Scope error. Token does not contain scopes

In my application each administrator has app_metdata attribute that defines whether or not they have the admin role. I am using a rule (below) to add the admin scope if the user has this metadata.However, any API calls using the token returns an insufficient scope error. I have used jwt.io to verify that NO scopes are returned in my token. What do I have to do to ensure my authorized scopes are included in the JWT?
function (user, context, callback) {
var _ = require("lodash");
var req = context.request;
var scopes = (req.query && req.query.scope) || (req.body &&
req.body.scope);
// Normalize scopes into an array
scopes = (scopes && scopes.split(" ")) || '';
if (user.app_metadata !== undefined && user.app_metadata.roles !==
undefined && user.app_metadata.roles.indexOf('admin') >= 0) {
scopes.push("admin");
}
// Restrict the access token scopes according to the current user
//context.accessToken.scope = restrictScopes(user, scopes);
console.log('scopes',scopes.join(" "));
context.accessToken.scope = scopes.join(" ");
callback(null, user, context);
}
The rule looks correct. But the problem may be with loadash. I have used Authorized extension to add roles, permission, and group to users. It updates the user app_metadata field. To add the user's permissions in the scope, I used the following rule.
function (user, context, callback) {
if (context.request.query.audience === '[api identifier]' &&
context.clientID === '[client id]') {
var req = context.request;
var scopes = (req.query && req.query.scope) || (req.body && req.body.scope);
var permissions = user.permissions || [];
var requestedScopes = context.request.body.scope || context.request.query.scope;
var filteredScopes = requestedScopes.split(' ').filter( function(x) {
return x.indexOf(':') < 0;
});
Array.prototype.push.apply(filteredScopes, permissions);
console.log(filteredScopes.join(' '));
context.accessToken.scope = filteredScopes.join(' ');
}
callback(null, user, context);
}
https://auth0.com/docs/architecture-scenarios/spa-api/part-2#configure-the-authorization-extension
Make sure to restrict the permission to specific API and client. Otherwise, you might provide access to management API in the token mistakenly. If you are not using authorized extension, you can get the correct permission form the user object (user_metadata).
Alternatively, to add any specific API scope in the token for the API access, you can request the scope when you are calling /oauth/token or /authorize endpoint.
The /authorize endpoint is used for implicit grant , authorization code grant flow and authorization code grant with PKCE. The purpose of this call is to obtain consent from the user to invoke the API (specified in the audience field) and do certain things (specified in scope) on behalf of the user. Auth0 will authenticate the user and obtain consent, unless consent has been previously given. If you alter the value in scope, Auth0 will require consent to be given again. It should be executed in the browser
https://YOUR_AUTH0_DOMAIN/authorize?
audience=API_IDENTIFIER&
scope=openid%20email%20profile%20read:user&
response_type=token%20id_token&
client_id=YOUR_CLIENT_ID&
redirect_uri=https://YOUR_APP/callback&
state=123&
nonce=234
On the other hand, /oauth/token endpoint is used to implement clent credentials grant and resource owner password credentials grants. The following curl command ask for a token. It is using Resouce owner password credentials grant
curl --request POST \
--url 'https://YOUR_AUTH0_DOMAIN/oauth/token' \
--header 'content-type: application/json' \
--data '{"grant_type":"password","username": "user#example.com","password": "pwd","audience": "https://someapi.com/api", "scope": "read:sample", "client_id": "YOUR_CLIENT_ID", "client_secret": "YOUR_CLIENT_SECRET"}'
Note: You have to use Access token for API call.
Additionality, you can try adding admin role or permission as custom claim using rule in the access token or id_token. Based on the claim, you can restrict the access. For example,
function (user, context, callback) {
const namespace = 'https://myapi.com/';
context.idToken[namespace + 'user_metadata'] = user.user_metadata;
context.accessToken[namespace + 'user_metadata'] = user.user_metadata;
callback(null, user, context);
}

How to post on wall when app is in development mode?

I have a new web app in development mode, and am trying to post to a users wall using something like this:
<fb:login-button scope="publish_pages" autologoutlink="true" onlogin="OnRequestPermission();">
</fb:login-button>
...
var params = {};
params['message'] = 'Message';
params['name'] = 'Name';
params['description'] = 'Description';
params['link'] = 'http://www.example.com';
params['picture'] = 'http://example.com/example.png';
params['caption'] = 'Caption';
FB.api('/me/feed', 'post', params, function(response) {
if (!response || response.error) {
console.log(response.error);
} else {
alert('Published to stream - you might want to delete it now!');
}
});
I am testing this after a successful login using the FB account defined in that app as admin, but am getting an OAuthException error:
"(#200) The user hasn't authorized the application to perform the action"
Do I need to send the app through review to get additional access even though we are in testing? Is there something else I missed here?
Thanks
You are using the wrong permission, you would need publish_actions to post to the user wall. publish_pages is for posting to a Page you own. You do not need to go through the review process for testing, all permissions work without review for users with a role in the App.

Issue using Insights Edge API

I am trying to get some insights data using Insights Edge API, but running into permissions issue:
Here is the code I am using:
string applicationId = "";
string applicationSecret = "";
string accountId = "";
System.Net.WebClient client = new System.Net.WebClient();
string accessToken = client.DownloadString("https://graph.facebook.com/oauth/access_token?client_id=" + applicationId + "&client_secret=" + applicationSecret + "&grant_type=client_credentials").Replace("access_token=","");
System.Net.WebRequest req = System.Net.WebRequest.Create("https://graph.facebook.com/v2.4/act_"+accountId+"/insights?access_token=" + accessToken);
System.Net.WebResponse response = req.GetResponse();
using(System.IO.StreamReader sr = new System.IO.StreamReader(response.GetResponseStream()))
{
string s = sr.ReadToEnd();
Console.WriteLine(s);
}
I am getting the following JSON back:
{
"error": {
"message": "(#10) You do not have sufficient permissions to perform this action",
"type": "OAuthException",
"code": 10
}
}
Application in question was created under the same Facebook account as the ad account. What do I need to check in account/application settings to see if I have all the correct permissions to access Ad Insights API? The code will need to run in the service that doesn't require user intervention, is application access token the right way to access ad insight data in this case?

How to get the access token automatically in facebook

I'm trying to make some sort of dashboard of my facebook in R. Some basic stuff. I would like to automate the script so that it can periodically update itself. I use knitr and task manager to produce the dashboard, which works well.
I use the facebook code of romainfrancois' blog to get the facebook data:
facebook <- function( path = "me", access_token = token, options){
if( !missing(options) ){
options <- sprintf( "?%s", paste( names(options), "=", unlist(options), collapse = "&", sep = "" ) )
} else {
options <- ""
}
url <- sprintf( "https://graph.facebook.com/%s%s&access_token=%s", path, options, access_token )
# print(url)
data <- getURL( url )
fromJSON( data )
}
The only problem is to get the access token automatically.
I tried to webscrape the token of the webpage:
library(RCurl)
FBdevPage<-browseURL("http://developers.facebook.com/tools/explorer")
FBdevPage[21]
It should be on line 21, according to the source code of the page. However, in R it only shows a backslash. Does someone had any ideas to get the access token? Or otherwise, store the procedure, while it allows to retrieve the data each time?