"An access token is required to request this resource" - Facebook graph API - android

I'm trying to use the facebook Graph API in my android application to retrieve the last posts from a Facebook Page. I have everything set up, so I can login with any account and even make a "/me" request to get the user's basic info. But when I try to make this request:
new Request(Session.getActiveSession(),
"PokerNewsBrazil?fields=posts&fref=ts/posts",
null,
HttpMethod.GET,
new Request.Callback() {
public void onCompleted(Response response) {
/* handle the result */
}
}
).executeAsync();
I receive the following error: "An access token is required to request this resource".
But my access token exists and it is valid, because if I use the access token from the same session in the Graph API Explorer I receive a succesfull response containing the posts from that page.
Where am I getting it wrong?

Change HttpMethod.GET to HttpMethod.POST.
This error arises because the SDK posts the access token behind the scenes, while the API is looking for it in a GET parameter.
For some reason using HttpMethod.GET and appending the access token to the url string causes various malformed access token errors.
I also encountered various errors when batching requests. If you encounter such errors, try executing a request standalone and debug from there.
The Facebook SDK is iterating relatively quickly yet the documentation is lacking and not up to date. Stick with it.

Related

Google oauth2 works with one time code generated from Android but not working for code generated from JS SDK

I am trying to authenticate the user using oauth2 api from Google. There are 2 platforms, Android and Web. For new users, I am fetching the one-time auth code on the client and sending it to the server on both platforms. Once server receives the code, it is fetching the access token and after that, the user details. The server is able to fetch the token from the one-time auth code sent from Android device, but it is failing for the code sent from Web.
This is my code snippet in JS for fetching one-time auth code..
gauth2.grantOfflineAccess({
'scope': 'profile email',
'redirect_uri': 'postmessage'
}).then(function(e){
if(!e){
// Error
}
else{
console.log('Auth code: '+e.code);
}
});
On server side, this is the POST request that I am doing to fetch the token from one-time code..
post_data = {'code': one_time_code, 'client_id': settings.GOOGLE_OAUTH2_CLIENT_ID, 'client_secret': settings.GOOGLE_OAUTH2_CLIENT_SECRET, 'grant_type': 'authorization_code'}
req = urllib2.Request("https://www.googleapis.com/oauth2/v3/token", data=urllib.urlencode(post_data), headers={'User-Agent': 'Mozilla/5.0'})
req.get_method = lambda: 'POST'
res = urllib2.urlopen(req)
if res.code == 200:
print "response 200 : "
else:
print "Access Token Validation Return Code: ", res.code
This web service call returns 200 and token when the auth-code is generated from Android. When it is sent from web, the same method throws the following error..
Error: 400, invalid request; missing parameter 'redirect_uri'
In this case, I don't need to send any redirect_uri, because I am reading the response there itself. But I still tried setting an empty value and also tried setting it to some value that exactly matches one of the values in google developers console. In that case, I am still getting..
Error: 400, invalid request; redirect_uri mismatch.
I cannot get my head around the fact that this web service call is working perfectly for android codes and not for web codes. Please note that scopes are different for Android app and Web app. But still, this seems to be some fundamental error. Any help would be appreciated.

Accessing Facebook Graph API without login

I've seen that with Javascript API and via GET requests, it is possible to get public posts from FanPages.
What i'm trying to acomplish is an Android Native App that doesn't ask user to get logged and with the FB App access token gets and shows the posts from the FB Page.
I'm wondering if this is possible via Android FB API as I can accomplish this via urls like
https://graph.facebook.com/{page_id}/feed?fields=message,picture&limit=10&access_token={your_acces_token}
When i'm trying this with Android Graph API, without user loging,
AccessToken.getCurrentAccessToken()
returns null
Thank you
I was struggling with the same for a while and after hours of research I came up with this (source):
#Override
protected void onCreate(Bundle savedInstanceState) {
FacebookSdk.sdkInitialize(getApplicationContext());
AppEventsLogger.activateApp(getApplication());
AccessToken at = new AccessToken(getString(R.string.facebook_access_token), getString(R.string.facebook_app_id), getString(R.string.facebook_page_id), null, null, null, null, null);
Bundle parameters = new Bundle();
parameters.putString("fields", "message,created_time,link,full_picture");
new GraphRequest(at, "/" + at.getUserId() + "/feed", parameters, HttpMethod.GET, new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
Log.i(this.getClass().getName(), "onCompleted " + response.getRawResponse());
}
}).executeAsync();
}
I assume you already have a page access token. I created mine with the graph explorer from facebook. Here is a tutorial on how to create a never expiring one:
How to get a never expiring Facebook Page Access Token (look for the 2016 Method)
As far as I know, the extended token does not expire as long as it is used. But I am not sure about that. I think I red this somewhere in the facebook api docs but cannot find it anymore.
There are a lot other parameters you can set. See here Page and look for 'Fields'
Hope this clumsy solution is helpfull to someone.
There are two ways to do this and they are both documented here.
The simpler method is to simply concatenate your AppID and AppSecret (found in your Facebook developer dashboard) with a "|" character like so: 'App ID' + '|' + 'App Secret'
BE WARNED!
This will expose your App's Private Credentials in Client Side Code if someone decides to look carefully. Therefore it is much safer to setup a private backend server to act as a proxy for your mobile application's user-less access to the graph API.
You could set up an API in any language of your choice with a single public route that simply copies the request it receives, appends the credentials, sends the request to Facebook, and pipes Facebook's response back to the original requestor.
For Example:
Without Access Token:
Mobile App ---> http://www.YourServerDomain/{page_id}/feed?fields=message,picture&limit=10
With Access Token:
Your Server ---> http://graph.facebook.com/{page_id}/feed?fields=message,picture&limit=10&access_token=AppID|AppSecret
Response Pipeline
Facebook ---> API RESULT ---> Your Server ---> API RESULT ---> Mobile App

Create Facebook access token without logging in

I want to receive the public posts of a defined facebook page in my app. I already integrated the FacebookSDK and created a new app in the Facebook developer console. My Request looks like this:
new Request(
null,
"/176063032413299/feed",
null,
HttpMethod.GET,
new Request.Callback() {
public void onCompleted(Response response) {
tv.setText(response.getRawResponse());
}
}
).executeAsync();
The server answers, that I need an acceess token. But I don't want my users to be logged in, when they use my app. So is there an option to get an access token without being logged in? I only want to read public data. I am not interested in publishing or reading private posts.
If I use the app access token like this, it still does not work:
new Request(
null,
"/176063032413299/feed?access_token=xxx",
null,
HttpMethod.GET,
new Request.Callback() {
public void onCompleted(Response response) {
tv.setText(response.getRawResponse());
}
}
).executeAsync();
I get the response:
"Invalid OAuth access token signature"
Even for public posts, you have to authorize the user in order to get access. Either with read_stream to get ALL posts or with user_status to get the posts of the user only.
read_stream will most likely not get approved by Facebook though, see this document: https://developers.facebook.com/docs/facebook-login/permissions/v2.2
Keep in mind that "public" does not mean you can grab it without user authorization. Apps can´t just scrape what they want - scraping is not allowed anyway: https://www.facebook.com/apps/site_scraping_tos_terms.php
Also, of course you can´t create a User Token (which is what you need) without user interaction (login and authorization). Detailed information about Access Tokens can be found in the following links:
https://developers.facebook.com/docs/facebook-login/access-tokens/
http://www.devils-heaven.com/facebook-access-tokens/
Btw, the docs mention that "Any valid access token is required to view public links." - So you may be able to get links only.
Source: https://developers.facebook.com/docs/graph-api/reference/v2.2/user/feed
For debugging Access Tokens, use the Facebook Debugger: https://developers.facebook.com/tools/debug/
Edit: I just realized that you just want to grab the public feed of a Facebook Page, not a User Profile. For that, you can just use an App Access Token. It´s never expiring and easy to create: App-ID|App-Secret. Check out the docs for more information. Keep in mind that you would need to use a User Token or Page Token if the Page is restricted by age or country.
Have a look at https://developers.facebook.com/docs/graph-api/reference/v2.2/page/feed/
The permissions needed to be able to request /{page_id}/feed:
An access token is required to view publicly shared posts.
A user access token is required to retrieve posts visible to that person.
A page access token is required to retrieve any other posts.
Meaning you could generate a long-living Page Access Token to be able to retrieve the public Page Posts. As you won't want to store an expiring Access Token in your App, you'll have to create a backend web service to proxy the requests between the Graph API and your app.
See
https://developers.facebook.com/docs/facebook-login/access-tokens/#pagetokens
https://developers.facebook.com/docs/facebook-login/access-tokens/#extendingpagetokens
https://developers.facebook.com/docs/facebook-login/access-tokens/#refreshtokens
You should also be able to use an App Access Token, which is valid indefinitely.
Use client token.
You could also generate and sign your own personal token but you don't want to distribute that.

Best way to handle 401 errors with spring android

I have an android app which uses the spring android library to communicate with my restful api. I'm not sure how to handle the scenario when the token for my client expires. What I'd like to to is to capture any 401 error and simply fetch a new token and retry the request.
I've created a ResponseErrorHandler and wired that up to my rest template:
public class UnauthorizedErrorHandler implements ResponseErrorHandler {
....
public void handleError(ClientHttpResponse response) throws IOException {
if (response.getStatusCode().value() == HttpStatus.SC_UNAUTHORIZED) { // 401 error
// fetch a new token
// Retry request now that we have a new token????
}
}
}
My problem is that I have no access to the originating request in the Response error handler. Unless I'm missing something, this strategy seems reasonable, but I'm not sure how to make it work. This also seems like a typical scenario for any client that is working with OAuth tokens, so hopefully someone out there can point me in the right direction.
If the token has expired then you should ask the user to login again.
Think about a user removing your OAuth app access, your app will received an expired token or similar error, and you should have the user login and give your app access again.
If you are not referring to an OAuth token, but your own API, then your should create some sort of mechanism to update the token to be used by the client. For example, you can send a header with the new token on your response asking the user to start using the new value from that point onwards, or as part of the response body or a push notification requesting a token exchange, etc.

Facebook auth token exchange

Is it possible to authenticate the user on server side using auth token retrieved by Android applicaton from Facebook?
In other words Android application uses SSO and obtain auth token. Then sends this token to backend application deployed on Google App Engine. Then backend application verifies the user against Facebook using the token.
I guess it's not feasible because retrieved token can be used only by Android application, but who knows? Maybe it may be reused somehow?
The Token you get from Android API can be sent to your server, who can check the validity of the token by querying the graph ( using /me?auth_token=.... for example).
The problem is that the same token can be used by any third party - it's not client specific - and so if you base server identification based on that, you have a problem (since a third app could use its user token and get authenticated by you). I am trying to find a way to solve this issue, but I don't have good ideas yet...
Facebook actually has an Android SDK that lets you do this. Information can be found here.
Yes you can. A valid access token is a valid access token. The Graph API does from where the token came, but only that the token has the appropriate permissions to access that portion of the graph api. Keep in mind, though, that the token is only valid for 24 hours from the time of its issuance. (is that really a word?) From the time it is issued?
When using facebook android sdk with SingleSignOn (SSO), the access token format actually changed.
Instead of getting traditional auth token which contains userid & session key as a part of authToken
now we get a different format of authToken
As Facebook Devs are still in process to support there rest apis with newly formated access token
meanwhile we can disable the SSO on android facebook sdk by changing DEFAULT_AUTH_ACTIVITY_CODE to -1 from 32665 (in Facebook.java)
This will invoke Traditional dialouge for granting acess token and in return you'll get access token which will contain session key in it.
Those who are looking for generating secure session key you need to add your own method in Facebook.java like
public String getSessionSecret(String accessToken) throws MalformedURLException, IOException
{
Bundle b = new Bundle();
b.putString("method", "auth.promoteSession");
b.putString("access_token", accessToken);
b.putString("session_key_only", "true");
String response = request(b);
return response;
}

Categories

Resources