0

I'm trying to get an access token on android device in Java.

At first I've created Client ID for installed applications (Android) in Google API Console, and set the package where the access token will be requested, and SHA1 fingerprint.

As I read in OAuth2ForDevices, to obtain an access token, I have to obtain a User code at first. So I tried to send POST request with client_id and scope using Aquery like this:

AQuery aq = new AQuery(activity);
         aq.ajax("https://accounts.google.com/o/oauth2/device/code?" +
                "scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile" +
                "client_id=xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
            JSONObject.class,new AjaxCallback<JSONObject>(){

           @Override
           public void callback(String url, JSONObject traffic_flow, AjaxStatus status) {

               publishProgress(traffic_flow.toString());

           }
    });

The problem is that JSONObject traffic_flow is allways null. I also tried to get it using this (but I don't thing this is a right way):

authToken = GoogleAuthUtil.getToken(activity, mEmail,  "audience:server:client_id:xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com");

where mEmail is the email from the android device, but I got GoogleAuthException "Unknown". How can I obtain the User code properly?

EDIT:

I was finally able to obtain an auth token using this:

String scope = "audience:server:client_id:xxxxxxxxxxxx.apps.googleusercontent.com";
String token = GoogleAuthUtil.getToken(activity, client.getAccountName(), scope);

where scope is a Client ID for web applications which was generated in Google API Console (afterwards I'm sending the token to my website and verifying it), Client is PlusClient (more in Getting started with Google+).

I've obtained the token in my test application, now the problem is that when I wanted to include the code to my new application, I'm again getting that ugly exception:

com.google.android.gms.auth.GoogleAuthException: Unknown at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)

All the client IDs for these applications are in the same project, permissions in manifest should be ok (GET_ACCOUNTS,USE_CREDENTIALS,AUTHENTICATE_ACCOUNTS,INTERNET,ACCESS_NETWORK_STATE). The only change I've made in the new application is setting scopes when creating PlusClient because it doesn't work without it (don't know why it works without it in my test application)

mPlusClient = new PlusClient.Builder(this, this, this)
            .setVisibleActivities("http://schemas.google.com/AddActivity")
            .setScopes(Scopes.PLUS_LOGIN, Scopes.PLUS_PROFILE)
            .build()

What am I missing?

Community
  • 1
  • 1
DropDropped
  • 1,253
  • 1
  • 22
  • 50
  • I spent a day getting this working for Google Coordinate API about 2 weeks ago, sadly my code for this is on my work laptop, which I won't be able to get on till Thursday. I seem to recall this article giving me a push in the right direction; http://blog.tomtasche.at/2013/05/google-oauth-on-android-using.html Good Luck! I'll favourite this question to try and remind me to check-in when I have access to the code. – Robadob Jul 29 '13 at 21:19
  • make sure your scope string is in the form `oauth2:https://www.googleapis.com/auth/glass.timeline https://www.googleapis.com/auth/userinfo.profile` I recall that being one of my issues. – Robadob Jul 29 '13 at 21:26
  • You will not get access token this way but a user code and device code. This flow is for devices with limited input capabilities. Can you confirm if that is your requirement? – rnk Jul 29 '13 at 21:28
  • @rnk In [OAuth2ForDevices](https://developers.google.com/accounts/docs/OAuth2ForDevices) is stated that with User code I can request an access code, so this is why I'm trying to obtain User code at first. Anyway, my aim is to get an Access token from an android device. – DropDropped Jul 29 '13 at 21:37
  • 1
    That documentation is for resource/input constrained devices, like consoles with limited keyboard etc. If all you want is to use OAuth2 and get Access token after OAuth flow from the user you should use standard Google Sign In https://developers.google.com/+/mobile/android/getting-started – rnk Jul 29 '13 at 21:38
  • If you want to work with a PlusClient, why don’t you just call http://developer.android.com/reference/com/google/android/gms/plus/PlusClient.html#connect() ? – Tim Bray Aug 14 '13 at 03:10

2 Answers2

1

If you have to use this API then you should use POST version of AQuery and pass the POST parameters properly as below. This API OAuth2ForDevices is meant for resources constrained devices where the user has another way of authorizing your app.

params.put("scope", "your scopes");
params.put("client_id", "your client id");

AQuery aq = new AQuery(activity);
aq.ajax("https://accounts.google.com/o/oauth2/device/code", params, JSONObject.class, 
  new AjaxCallback<JSONObject>() {
           @Override
           public void callback(String url, JSONObject traffic_flow, AjaxStatus status) {
               publishProgress(traffic_flow.toString());
           }
});

However, if your requirement is to use regular OAuth2 with Android on say an Android phone with regular input capabilities then the standard OAuth mechanism with Android is this.

rnk
  • 2,394
  • 1
  • 19
  • 19
  • What I'm trying to do is to send a request to my website, using the access token, so then I can verify it using google public keys, and send back response. I tried it with your approach, even with [OAuth2InstalledApp](https://developers.google.com/accounts/docs/OAuth2InstalledApp) where are some additional parameters, but I always get network error with null response. I could sign in using the link you wrote, but is it possible to obtain access code using it? – DropDropped Jul 30 '13 at 09:35
  • can you please help me on this bug http://stackoverflow.com/questions/21445265/google-coordinate-authentification – haythem souissi Jan 30 '14 at 00:01
1

This is the code I use for getting an OAuth 2.0 token for use with the Google Coordinate api, I run it within an ASyncTask. I've not included the part for generating DESIRED_USER as that uses startActivityForResult() on some AccountManager intent. Hopefully you can use this.

You should replace SCOPE with yours, which i think should be oauth2:https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile

import android.accounts.Account;
import android.accounts.AccountManager;

final String SCOPE = "oauth2:https://www.googleapis.com/auth/coordinate";
AccountManager accountManager = AccountManager.get(context);
//Kill Current token
accountManager.invalidateAuthToken("com.google",authManager.getToken());
//Fetch userAccount
Account userAccount = null;
for(Account account : accountManager.getAccounts())
    if(account.name.equals(DESIRED_USER))
    {
        try {
            return accountManager.blockingGetAuthToken(userAccount, SCOPE, false);
        } catch (Exception e) {
            System.out.println("Error: "+e.toString());
            e.printStackTrace();
        }
    }
return null;
Robadob
  • 5,319
  • 2
  • 23
  • 32
  • Thank you for your response, unfortunately I wasn't able to get the token this way - I've received null when using `accountManager.blockingGetAuthToken(account, "oauth2:https://www.googleapis.com/auth/userinfo.email", false);` – DropDropped Aug 10 '13 at 23:28
  • The docs say, Returns An auth token of the specified type for this account, or null if authentication fails or none can be fetched. Perhaps the account you are using does not have G+? Otherwise I would expect it to throw an exception. "http://developer.android.com/reference/android/accounts/AccountManager.html#blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) – Robadob Aug 11 '13 at 09:39
  • Since when did the GoogleAuthUtil.getToken() method start throwing a GoogleAuthException with message "BadUsername" for an email that is not registered on a device, instead of the previous exception IllegalArgumentException with message "Non existing account 'email_address'" ? http://developer.android.com/reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context , java.lang.String, java.lang.String) – Etienne Lawlor Nov 06 '13 at 02:32
  • Hey @Robadob, this used to work for me, but only a few days ago it stopped working and now it throws this error `com.google.android.gms.auth.GoogleAuthException: Unknown.` Any idea why? Is there something wrong with my scopes? https://gist.github.com/lawloretienne/7351151 – Etienne Lawlor Nov 07 '13 at 16:54
  • can you please help me on this bug http://stackoverflow.com/questions/21445265/google-coordinate-authentification – haythem souissi Jan 30 '14 at 00:01
  • can you please help me on this bug http://stackoverflow.com/questions/21445265/google-coordinate-authentification – haythem souissi Jan 30 '14 at 00:02