Facebook graph API fail to load resource bad request 400 - facebook-graph-api

I have the following code on my controller.js and works when I request from Facebook Graph 2.4
request.open("GET","https://graph.facebook.com/v2.4/katyperry/posts?"+access_token,true);
However this only returns few fields: message, story, created_time, and id.
I need some additional more fields: message, picture, likes, created_time, link, type, comments and object_id.
So I tried the following:
request.open("GET","https://graph.facebook.com/v2.4/katyperry?fields=posts.limit(2){message,picture,likes,created_time,link,type,comments,object_id}"+access_token,true);
The last one sent me the error:
Failed to load resource: the server responded with a status of 400 (Bad Request)
I tested both options the request on the Graph API Explorer and it worked properly. How can I get those extra fields? what am I missing?
I am adding the precedent code to show how access_token is builded:
var appID ="138429819833219";
var appSecret ="dada0a4d7f7717b0d37fd637d9e1522a";
var accessTokenRq = makeHttpRequest();
var httpString = 'https://graph.facebook.com/oauth/access_token?grant_type=client_credentials&client_id='+appID+'&client_secret='+appSecret;
accessTokenRq.open("GET",httpString,true);
accessTokenRq.send(null);
var access_token;
accessTokenRq.onreadystatechange = function() {
if (accessTokenRq.readyState == 4) {
access_token = accessTokenRq.responseText;
//alert("Hat geklappt - Trabajó :)");
var request = makeHttpRequest();
// the following request works
request.open("GET","https://graph.facebook.com/v2.2/katyperry/posts?"+access_token,true);
// next one don't - I checked inspector and access_token contains: 138429819833219|CewVrYOd86ctJ0HTP2X0XAS9m4o
request.open("GET","https://graph.facebook.com/v2.4/katyperry?fields=posts.limit(2){message,picture,likes,created_time,link,type,comments,object_id}"+access_token,true);

What is contained in the access_token variable? The request
/katyperry?fields=posts.limit(2){message,picture,likes,created_time,link,type,comments,object_id}
works in the Graph API Explorer, so I guess your access_token variable only contains the actual access token, and not the parameter key/value pair.
This
request.open("GET","https://graph.facebook.com/v2.4/katyperry?fields=posts.limit(2){message,picture,likes,created_time,link,type,comments,object_id}&access_token="+access_token,true);
should hopefully work then.

The error it was syntax, the right code as follow:
request.open("GET","https://graph.facebook.com/v2.4/katyperry/posts?limit=2&fields=message,picture,likes,created_time,link,type,comments,object_id&"+access_token,true);

Related

How to get Facebook page feed and Filter its fields as Json using Google App script

I am trying to get a Facebook page feed through Google app script.
As of now I tried different scripts but I am getting only app token with the request and if i change it with a usertoken from graph api I got messages but no images and titles
How to get the user token and get the correct fields for as a json ,
var url = 'https://graph.facebook.com'
+ '/love.to.traavel/feed'
+ '?access_token='+ encodeURIComponent(getToken());
// + '?access_token=' + service.getAccessToken();
var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true});
var json = response.getContentText();
var jsondata = JSON.parse(json);
Logger.log(jsondata); //check this and adjust following for loop and ht
var posts = {};
for (var i in jsondata) {
posts[i] = {"post":jsondata[i].message};
}
return posts;
You should use a Page Token, not a User Token
You need to ask for fields you want to get, with the fields parameter: https://graph.facebook.com/love.to.traavel/feed?fields=field1,field2,...&access_token=xxx
You get a user token by authorizing your App: https://developers.facebook.com/docs/facebook-login/platforms
Be aware that extended user tokens are valid for 60 days only, so you have to refresh it once in a while. There is no user token that is valid forever. You cannot authorize through code only, it needs user interaction. The easiest way is to just generate a user token by selecting your App in the API Explorer and authorize it, like you did already. Then hardcode it in the script code.
Alternatively, you can try implementing this with the manual login flow, check out the docs for that. You can try adding the functionality using this for a custom interface where you go through the login process: https://developers.google.com/apps-script/guides/html/
Since you don´t own the page, you should read this too: https://developers.facebook.com/docs/apps/review/feature/#reference-PAGES_ACCESS

Can you add a cookie to request with asp.net core middleware?

Am trying to write custom middleware in the ASP.net core pipeline, as part of my invoke, would like to append/add cookie, so then next middleware in the pipeline can access those cookie.
getting compiling error on set the cookie value. Can anyone recommend work around for this.
Note: When I tried with Response.Cookie , it works but only problem is, cookie is reflecting only on next request from the browser, but I need this to be reflecting on the next middleware in the pipeline immediately after execute this.
below code snippet
public async Task Invoke(HttpContext httpContext)
{
var queryParameters = httpContext.Request.Query;
var cookies = httpContext.Request.Cookies;
if (!cookies.ContainsKey(".AspNetCore.Session")
|| cookies[".AspNetCore.Session"] != "new_key")
{
httpContext.Request.Cookies[".AspNetCore.Session"] = "new_key";
}
await _next.Invoke(httpContext);
}
You cannot use cookie's value in same request. However, you could use good old HttpContext.Items.
public async Task InvokeAsync(HttpContext context)
{
context.Request.HttpContext.Items["key"] = "Hello!";
await _next(context);
}
You then retrieve it as
var value = HttpContext.Items["key"];
In my case I have an AuthorizationHandler that performs some checks to determine the user details and whether the user is logged in. The auth handler stores some of this info in a token in the request headers, so it can be easily accessed by the controllers.
When the user is logged in, this token can be read from the HttpContext.Request.Headers in a standard controller and all is well.
When the user is not logged in, the auth handler returns failure and so the request is redirected to "/login". Sadly the token header is not preserved across the redirect, so in my LoginController the token is null.
The only way I could make the token available to both a standard controller and LoginController is to store the token in both the request headers AND response cookies. This cookie can be read from the LoginController in the HttpContext.Request.Cookies collection. I set it to be short-lived as it's only needed briefly (it'll disappear after 5 seconds)
Here is part of the code from my auth handler:
HttpRequest request = _httpContextAccessor.HttpContext.Request;
HttpResponse response = _httpContextAccessor.HttpContext.Response;
request.Headers["X-Token"] = encryptedToken;
response.Cookies.Append("TokenCookie", encryptedToken, new CookieOptions
{
MaxAge = TimeSpan.FromSeconds(5),
Secure = true,
IsEssential = true,
});

Identity Server 3 Facebook Login Get Email

Identity server is implemented and working well. Google login is working and is returning several claims including email.
Facebook login is working, and my app is live and requests email permissions when a new user logs in.
The problem is that I can't get the email back from the oauth endpoint and I can't seem to find the access_token to manually request user information. All I have is a "code" returned from the facebook login endpoint.
Here's the IdentityServer setup.
var fb = new FacebookAuthenticationOptions
{
AuthenticationType = "Facebook",
SignInAsAuthenticationType = signInAsType,
AppId = ConfigurationManager.AppSettings["Facebook:AppId"],
AppSecret = ConfigurationManager.AppSettings["Facebook:AppSecret"]
};
fb.Scope.Add("email");
app.UseFacebookAuthentication(fb);
Then of course I've customized the AuthenticateLocalAsync method, but the claims I'm receiving only include name. No email claim.
Digging through the source code for identity server, I realized that there are some claims things happening to transform facebook claims, so I extended that class to debug into it and see if it was stripping out any claims, which it's not.
I also watched the http calls with fiddler, and I only see the following (apologies as code formatting doesn't work very good on urls. I tried to format the querystring params one their own lines but it didn't take)
(facebook.com)
/dialog/oauth
?response_type=code
&client_id=xxx
&redirect_uri=https%3A%2F%2Fidentity.[site].com%2Fid%2Fsignin-facebook
&scope=email
&state=xxx
(facebook.com)
/login.php
?skip_api_login=1
&api_key=xxx
&signed_next=1
&next=https%3A%2F%2Fwww.facebook.com%2Fv2.7%2Fdialog%2Foauth%3Fredirect_uri%3Dhttps%253A%252F%252Fidentity.[site].com%252Fid%252Fsignin-facebook%26state%3Dxxx%26scope%3Demail%26response_type%3Dcode%26client_id%3Dxxx%26ret%3Dlogin%26logger_id%3Dxxx&cancel_url=https%3A%2F%2Fidentity.[site].com%2Fid%2Fsignin-facebook%3Ferror%3Daccess_denied%26error_code%3D200%26error_description%3DPermissions%2Berror%26error_reason%3Duser_denied%26state%3Dxxx%23_%3D_
&display=page
&locale=en_US
&logger_id=xxx
(facebook.com)
POST /cookie/consent/?pv=1&dpr=1 HTTP/1.1
(facebook.com)
/login.php
?login_attempt=1
&next=https%3A%2F%2Fwww.facebook.com%2Fv2.7%2Fdialog%2Foauth%3Fredirect_uri%3Dhttps%253A%252F%252Fidentity.[site].com%252Fid%252Fsignin-facebook%26state%3Dxxx%26scope%3Demail%26response_type%3Dcode%26client_id%3Dxxx%26ret%3Dlogin%26logger_id%3Dxxx
&lwv=100
(facebook.com)
/v2.7/dialog/oauth
?redirect_uri=https%3A%2F%2Fidentity.[site].com%2Fid%2Fsignin-facebook
&state=xxx
&scope=email
&response_type=code
&client_id=xxx
&ret=login
&logger_id=xxx
&hash=xxx
(identity server)
/id/signin-facebook
?code=xxx
&state=xxx
I saw the code parameter on that last call and thought that maybe I could use the code there to get the access_token from the facebook API https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow
However when I tried that I get a message from the API telling me the code has already been used.
I also tried to change the UserInformationEndpoint to the FacebookAuthenticationOptions to force it to ask for the email by appending ?fields=email to the end of the default endpoint location, but that causes identity server to spit out the error "There was an error logging into the external provider. The error message is: access_denied".
I might be able to fix this all if I can change the middleware to send the request with response_type=id_token but I can't figure out how to do that or how to extract that access token when it gets returned in the first place to be able to use the Facebook C# sdk.
So I guess any help or direction at all would be awesome. I've spent countless hours researching and trying to solve the problem. All I need to do is get the email address of the logged-in user via IdentityServer3. Doesn't sound so hard and yet I'm stuck.
I finally figured this out. The answer has something to do with Mitra's comments although neither of those answers quite seemed to fit the bill, so I'm putting another one here. First, you need to request the access_token, not code (authorization code) from Facebook's Authentication endpoint. To do that, set it up like this
var fb = new FacebookAuthenticationOptions
{
AuthenticationType = "Facebook",
SignInAsAuthenticationType = signInAsType,
AppId = ConfigurationManager.AppSettings["Facebook:AppId"],
AppSecret = ConfigurationManager.AppSettings["Facebook:AppSecret"],
Provider = new FacebookAuthenticationProvider()
{
OnAuthenticated = (context) =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, ClaimValueTypes.String, "Facebook"));
return Task.FromResult(0);
}
}
};
fb.Scope.Add("email");
app.UseFacebookAuthentication(fb);
Then, you need to catch the response once it's logged in. I'm using the following file from the IdentityServer3 Samples Repository, which overrides (read, provides functionality) for the methods necessary to log a user in from external sites. From this response, I'm using the C# Facebook SDK with the newly returned access_token claim in the ExternalAuthenticationContext to request the fields I need and add them to the list of claims. Then I can use that information to create/log in the user.
public override async Task AuthenticateExternalAsync(ExternalAuthenticationContext ctx)
{
var externalUser = ctx.ExternalIdentity;
var claimsList = ctx.ExternalIdentity.Claims.ToList();
if (externalUser.Provider == "Facebook")
{
var extraClaims = GetAdditionalFacebookClaims(externalUser.Claims.First(claim => claim.Type == "urn:facebook:access_token"));
claimsList.Add(new Claim("email", extraClaims.First(k => k.Key == "email").Value.ToString()));
claimsList.Add(new Claim("given_name", extraClaims.First(k => k.Key == "first_name").Value.ToString()));
claimsList.Add(new Claim("family_name", extraClaims.First(k => k.Key == "last_name").Value.ToString()));
}
if (externalUser == null)
{
throw new ArgumentNullException("externalUser");
}
var user = await userManager.FindAsync(new Microsoft.AspNet.Identity.UserLoginInfo(externalUser.Provider, externalUser.ProviderId));
if (user == null)
{
ctx.AuthenticateResult = await ProcessNewExternalAccountAsync(externalUser.Provider, externalUser.ProviderId, claimsList);
}
else
{
ctx.AuthenticateResult = await ProcessExistingExternalAccountAsync(user.Id, externalUser.Provider, externalUser.ProviderId, claimsList);
}
}
And that's it! If you have any suggestions for simplifying this process, please let me know. I was going to modify this code to do perform the call to the API from FacebookAuthenticationOptions, but the Events property no longer exists apparently.
Edit: the GetAdditionalFacebookClaims method is simply a method that creates a new FacebookClient given the access token that was pulled out and queries the Facebook API for the other user claims you need. For example, my method looks like this:
protected static JsonObject GetAdditionalFacebookClaims(Claim accessToken)
{
var fb = new FacebookClient(accessToken.Value);
return fb.Get("me", new {fields = new[] {"email", "first_name", "last_name"}}) as JsonObject;
}

How to retrieve request info by request id?

When I invite my friends I get back request_ids. After that I proceed those ids to get info about users invites have been sent to and create records in my database based on user's public profile info. But when I try to get request info by request id I get error message saying "Unsupported get request" nevertheless access token is fine.
// create data object to be sent to FB API
var data = new Object();
data.method = 'apprequests';
data.message = MESSAGE_TEXT;
data.display = 'iframe';
data.access_token = ACCESS_TOKEN;
data.show_error = 'Yes';
data.title = TITLE_TEXT;
// call FB API
FB.ui(data, function(aResponse)
{
var request_ids = '';
if (aResponse && aResponse.request_ids)
request_ids = aResponse.request_ids.join(',');
if (request_ids)
{
// send request_ids string to my server for further processing
}
});
Example of such broken request id: 1930910810837. Trying to get info for it like this:
https://graph.facebook.com/1930910810837?access_token=ACCESS_TOKEN
Please help me understand what is wrong. May it be issue on Facebook side, for example, Facebook returned broken id for some reason? Thank you!!!

facebook create_event posts on my app's wall not the user's wall

i'm attempting to provide a facility on my site that allows a user to create a facebook event for their booking.
http://developers.facebook.com/docs/reference/api/event/
now im doing the correct process:
1) first getting authorisation from the user
https://graph.facebook.com/oauth/authorize?client_id=APP_ID&redirect_uri=http://urlimredirectingto.comtype=web_server
2) requesting for an access token with the "code" that is returned in step 1
https://graph.facebook.com/oauth/access_token
3) using the access_token to create the event ...
string facebookCreateUri = string.Format("https://graph.facebook.com/{0}/events", loggedInMember.FacebookUID);
var formData = new HttpUrlEncodedForm()
{
{"access_token", accessToken},
{"owner", loggedInMember.FacebookUID},
{"description", "nice event that should be on the owners wall"},
{"name", "event on the users wall"},
{"start_time", "1272718027"},
{"end_time", "1272718027"},
{"location", "rochester"},
{"privacy","OPEN"}
};
HttpContent content = HttpContent.Create(formData);
HttpClient client = new HttpClient();
var response = client.Post(facebookCreateUri, "application/x-www-form-urlencoded", content);
but the event is posted on my app's wall, not the user's wall. It shouldn't have anything to do with the authentication/access_token elements because i use the same process to post on the user's wall. (http://developers.facebook.com/docs/reference/api/status/) and that works just fine.
I came back with a solution, after a week of working at many features with Facebook SDK, it finally works!
protected void onPostEvent(object sender, EventArgs e)
{
if (CanvasAuthorizer.Authorize())
{
var fb = new FacebookWebClient(CanvasAuthorizer.FacebookWebRequest);
dynamic parameters = new ExpandoObject();
parameters.description = txtEvDett.Text;
parameters.name = txtEvName.Text;
parameters.start_time = DateTime.Now.ToString("yyyyMMdd");
parameters.end_time = DateTime.Now.AddDays(1).ToString("yyyyMMdd");
parameters.access_token = CanvasAuthorizer.FacebookWebRequest.AccessToken;
dynamic eventDet = fb.Post("me/events", parameters);
litEvent.Text = String.Format("You have created the event with ID: {0}", eventDet.id);
lnkEvent.Visible = true;
lnkEvent.NavigateUrl = String.Format("http://www.facebook.com/event.php?eid={0}", eventDet.id);
}
}
For events, you have to request the create_event permission.
You should use /me/events to post on your events.
I user the C# SDK for Facebook from Codeplex - last version available for dld (aug 2011 - v5.2.1).
Good luck!
I don;t see in your request for Authorization any permission.. base permissions are not enough to do the postings.
i used:
https://www.facebook.com/dialog/permissions.request?app_id=MY_APP_ID&next=MY_APP_URL&display=page&response_type=code&canvas=1&perms=publish_stream,user_about_me,email
This is in the context of a canvas app. where MY_APP_URL is the url from facebook of the app:
http://apps.facebook.com/MY_APP_NAME_OR_ID
See extended permissions for events and check event's page in documentation
[EDIT] - I came back, sorry, now i did a test, and indeed, it works for me, but only of i post on my app's wall; even if i provided the 'user_events' permission i get this error:
The remote server returned an error: (403) Forbidden when posting on a user's wall.
This being said, i also subscribe to this question.