Invalid OAUTH access token, when using an application access token, Android - android

As the title says, when I try to request to get the friends list with the field installed:
"me/friends?Fields=installed&access_token=..."
I get the following error in my logcat:
"Invalid OAuth access token"
When looking on the facebook api I see that installed needs to take an application access token. So I generated the application access token using the appId and app Secret using:
https://graph.facebook.com/oauth/access_token?grant_type=client_credentials&client_id=APP_ID&client_secret=APP_SECRET
Below is the code:
try {
JSONObject obj = Util.parseJson(mFacebook.request("me/friends?fields=installed&access_token=..."));
Log.d("json Response", obj.toString());
JSONArray array = obj.optJSONArray("data");
if (array != null) {
for (int i = 0; i < array.length(); i++) {
// String name = array.getJSONObject(i).getString("name");
String id = array.getJSONObject(i).getString("id");
Log.d("Friends: ",id);
}
}
}catch (Exception e){
Log.d("Friends:", e.getMessage());
}
Any one any ideas why its doing this I have been searching for ages.
Cheers

What you are getting after authentication is App Access Token.
Quoting : Authenticating as an App allows you to obtain an access token which allows you to make request to the Facebook API on behalf of an App rather than a User. This is useful, for example to modify the parameters of your App, create and manage test users, or read your application's insights for example. App access tokens can also be used to publish content to Facebook on behalf of a user who has granted a publishing permission to your application
from facebook docs.
What you need for your case is an user access token. Refer this.
A user needs to authenticate and grant access to your app for you have access to his friends list.
EDIT
For checking for a single user the url is
https://graph.facebook.com/{uid}?fields=installed&access_token=< ACCESS_TOKEN >
You are trying to get user friend list and then check if the app is installed. I don't think getting user friend list is possible without user access token.
EDIT 2
Assuming from your comment that you have the list of frind's. Then you need not call for each user instead you can use FQL.
https://graph.facebook.com/fql?q=SELECT uid,is_app_user from user where uid IN (uid1,uid2)
And if you have the user access token then you can directly do.
https://graph.facebook.com/fql?q=SELECT uid,is_app_user from user where uid IN (SELECT uid2 FROM friend WHERE uid1 = me())
Hope this solves your problem.

Don’t request /me/friends – because with an app access token the API won’t know who „me” is supposed to be – request /userid/friends instead.
Sorry, I was wrong before – the way to go is with an user access token, and just setting the request up against /me/friends…

Related

Store Google+ friends list on backend server

I've integrated Google+ sign-in in my Android application. Now I wan't to get the user's friend list and store it on the server. I can't get the friends list on the client app and send it to the server since the data can be easily tampered. So I thought about generating an access token using the following code and send it to the server, which the server will then use to query the Google+ API and get the user's friends.
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient);
Account account = new Account(accountName, GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
String scope = "oauth2:" + Constants.SCOPE_PLUS_LOGIN + " " + Constants.SCOPE_EMAIL;
try {
String accessToken = GoogleAuthUtil.getToken(getApplicationContext(), account, scope);
} catch (IOException | GoogleAuthException e) {
e.printStackTrace();
}
But is sending the access token to the server directly using https safe enough? Cause if the token is compromised then any third party can use it to steal the user's personal information.
Or is there any better way to fetch and store the signed in user's friend list on the server?
1) Always transfer access_tokens over HTTPS.
2) Don't build any way to get access_tokens from your server. Make sure the server only supports sending access_tokens to it.
3) access_tokens expire after one hour so the window for abuse is limited.

How to use facebook login to access data from backend server in Android app?

I am working on an app in which I have to use facebook login for accessing data from my backend server. I have search on this and got that:
First, the user will enter username and password of facebook then the request goes to server.
If user authenticated then fetch access token of user.
Send this access token on server.
The server will verify this access token.
I have successfully connected my app with facebook i.e, now user can logged from my app to facebook. But I don't now how can I get the access token of user and also how I can verify this access token on server.
Can you provide me some sample code for this. Please help me I am stuck in it from a long time.
I'm not sure if it is best practice, but this is how I do it.
When you log a user in Android on the client device via any of the SDKs, you get an user access token. The token can be accessed as follows
AccessToken token = AccessToken.getCurrentAccessToken();
if (token != null) {
Toast.makeText(getActivity(), token, Toast.LENGTH_LONG).show();
}
You can then pass this token to the backend as a POST variable:
'access_token': '32b409xceBV78d2932b409xceBV78d29'
Using a backend SDK, you can get the user info again. Here's a example in python
facebook_graph = facebook.GraphAPI(access_token)
If the email and fbid match the user information stored in your database, you grant access:
user = get_user(email=facebook_graph['email'], fbid=facebook_graph['fbid'])
login(request, user)
To access the data of the facebook user you have to take permissions and the following link may be useful for you. Just check it out...
https://developers.facebook.com/docs/howtos/androidsdk/3.0/fetch-user-data/

Obtaining a basic google auth-token from AccountManager

I want to obtain a Google Authtoken from the AccountManager that I can send to my Webservice (not hosted on App Engine) to authenticate the User (I just need the email address and eventually his name, if no permission is required for this).
What do I have to use for the "authTokenType" Paramter of the "getAuthToken" method?
And which google Api do I have to use to get the Users Email?
This is doable using OpenID Connect, however it's sort of experimental, so details could change in the future. If you get an OAuth token for the 'https://www.googleapis.com/auth/userinfo.email' or 'https://www.googleapis.com/auth/userinfo.profile' scope you can use it to get user info from https://www.googleapis.com/oauth2/v1/userinfo (including email). Of course the user needs to authorize this.
You should theoretically be able to get the token from AcccountManager using the "oauth2:https://www.googleapis.com/auth/userinfo.profile" as the token type, but that doesn't appear to work on my device (Galaxy Nexus with stock 4.0.4). Since getting a token via the AccountManager doesn't work (at least for now), the only reliable way is to use a WebView and get one via the browser as described here: https://developers.google.com/accounts/docs/MobileApps
There is a demo web app here that does this: https://oauthssodemo.appspot.com
(late) Update: Google Play Services has been released and it is the preferred way to get an OAuth token. It should be available on all devices with Android 2.2 and later. Getting a profile token does work with it, in fact they use it in the demo app
I have had problems with this as well, since I was not able to find anything like a reference. Perhaps this can help you (code copied from an Android example on using the account manager):
Somewhere in an event handler of your Android app, issue a request for an auth token to get the user's email address in Android:
_accountMgr = AccountManager.get(this);
Account [] accounts = _accountMgr.getAccounts();
Account account = accounts[0]; // For me this is Google, still need to figure out how to get it by name.
_accountMgr.getAuthToken(account, AUTH_TOKEN_TYPE, false, new GetAuthTokenCallback(), null);
In the callback, extract the access token:
private class GetAuthTokenCallback implements AccountManagerCallback<Bundle> {
public void run(AccountManagerFuture<Bundle> result) {
Bundle bundle;
try {
bundle = result.getResult();
final String access_token = bundle.getString(AccountManager.KEY_AUTHTOKEN);
// store token somewhere you can supply it to your web server.
} catch (Exception e) {
// do something here.
}
}
}
Make some request to your web server, supplying the access token.
On the web server, validate the access token and obtain the email address:
curl -d 'access_token=<this is the token the app sent you>' https://www.googleapis.com/oauth2/v1/tokeninfo
You should get something like this:
{
"issued_to": "<something>.apps.googleusercontent.com",
"audience": "<something>.apps.googleusercontent.com",
"scope": "https://www.googleapis.com/auth/userinfo.email",
"expires_in": 3562,
"email": "<users email address>",
"verified_email": true,
"access_type": "online"
}
or if something went wrong:
{
"error": "invalid_token",
"error_description": "Bad Request"
}
You can get the User's name with the Google+ People API. (It will not provide the user's email address).
If this is OK, you can use "Know who you are on Google" as the authTokenType.
There is a sample application provided by Google that demonstrates how to use the AndroidAccountManager in conjunction with the Google+ APIs.
Link: http://code.google.com/p/google-plus-java-starter/source/browse/#hg%2Fandroid

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;
}

Using authToken for Google Health Data

We have developed and published an app for Google Health. Now we want to avoid every time logging into the gmail account by asking username and password.
So as to do this i have heard that I can have following options.
1. OAuth
2. Account Manager
3.
The problem with OAuth is that it will go via Android -> Web App -> Health path so i will need to develop an web app as well which we dont wish to do it right now.
So I am trying to use Account Manager, here is my code with which I could get list of accounts and an valid authToken for the selected account.
AccountManager mgr = AccountManager.get(getApplicationContext());
System.out.println("Got account manager");
Account[] accts = mgr.getAccounts();
}
Account acct = accts[0];
AccountManagerFuture<Bundle> accountManagerFuture = mgr.getAuthToken(acct, "android", null, this, null, null);
Bundle authTokenBundle = accountManagerFuture.getResult();
System.out.println("Account name "+accts[0].name);
String authToken = authTokenBundle.get(AccountManager.KEY_AUTHTOKEN).toString();
System.out.println("Got token:"+authToken);
But now I am confused about how to use this token to access the health data.
For getting the demographic feed we used the following code,where we explicitly made user to login into our application.
String queryURL = "https://www.google.com/health/feeds/profile/ui/" + profileId +"/-/DEMOGRAPHICS";
getDemoGrInfoQuery = new Query(new URL(queryURL));
Feed dempGrResultFeed;
globals = new Globals();
dempGrResultFeed = healthService.query(getDemoGrInfoQuery, Feed.class);
And thus we used to get the Feed using the URL.
And now I want to skip the login process and use the above authToken for retrieving the feed. How can this be done?
Any help would be really appreciated!!!
Thanks in advance,
As the standard OAuth procedure is supposed to work, you open the OAuth URL in a WebView (or anything similar) with all the required parameters, users provide Google (not your app) with their user name and password, then google gives you a token which you can use for your future communications.
This way the user doesn't have to give you their login credentials. They give it only to google, and google gives you a token which will authenticate your app every time you use it.
I think you should be good to go with this, since it requires you to open a WebView only once, unless the user logs out of google using your application or denies access to your application.
After getting the token, you just start polling google with that token and never ask user for their login credentials. quite seamless.
UPDATE
After our conversation in chat, let me tell you that you'll have to register an application with google, which will give you an appID, this appID will be used by your Android app to tell google that it is requesting permission on behalf of the Application which this appID refers to.
UPDATE 2
open the Google OAUth with all the parameters, google will give you a code
use that code and create a POST request again to google, and google will now return a long lasting AccessToken
You can then use this AccessToken in all your future communications

Categories

Resources