12

I am trying to access the Gmail API using an Android application. I have successfully requested and received an access token using all available scope combinations. But it seems that every time I actually try to use the Gmail API command I am getting a 403 exception reading: Access not configured please use Google developers console to activate the api...

Needless to say the API is activated and a client key was created using the correct package name & sha1 code. Same client ID works well with Google Plus features.

Anyone having this issue or succeeded in connecting to the Gmail api from Android?

Thanks

Here's the log:

09-04 21:40:54.014: W/System.err(26717): com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
09-04 21:40:54.014: W/System.err(26717): {
09-04 21:40:54.014: W/System.err(26717):   "code" : 403,
09-04 21:40:54.014: W/System.err(26717):   "errors" : [ {
09-04 21:40:54.014: W/System.err(26717):     "domain" : "usageLimits",
09-04 21:40:54.014: W/System.err(26717):     "message" : "Access Not Configured. Please use Google Developers Console to activate the API for your project.",
09-04 21:40:54.014: W/System.err(26717):     "reason" : "accessNotConfigured"
09-04 21:40:54.014: W/System.err(26717):   } ],
09-04 21:40:54.014: W/System.err(26717):   "message" : "Access Not Configured. Please use Google Developers Console to activate the API for your project."
09-04 21:40:54.014: W/System.err(26717): }

Are there any other API's that need to be enabled in the API Console except Google+ API and Gmail API?

EDIT:

I have found out that using a WebView based authentication will result in an access token that will grant Gmail API access but this is not a valid solution because the token is short lived. As for now the GoogleAuthUtil will grant a token but it's privileges are not sufficient for using the Gmail API. anyone had success in connecting Android with the Gmail API and would like to share?

EDIT2:

Here are snippets of what I am doing:

Getting the token:

token = GoogleAuthUtil.getToken(MainActivity.this, Plus.AccountApi.getAccountName(mGoogleApiClient), scope);

Trying to fetch messages from the Gmail API:

GoogleCredential credential = new GoogleCredential().setAccessToken(token);
JsonFactory jsonFactory = new JacksonFactory();
HttpTransport httpTransport = new NetHttpTransport();

service = new Gmail.Builder(httpTransport, jsonFactory, credential).setApplicationName("GmailApiTP").build();
ListMessagesResponse messagesRespose;
List<Message> m = null;

ArrayList<String> ids = new ArrayList<String>();
ids.add("INBOX");
try {
    messagesRespose = service.users().messages().list("me").setLabelIds(ids).setQ("From: something")
            .execute();
    m = messagesRespose.getMessages();

} catch (IOException e) {
    e.printStackTrace();
}

The exception is caught when use the Gmail API service. In addition I have tried clearing the token and asking for a new one with the same result.

Eric D
  • 6,901
  • 1
  • 15
  • 26
TalMihr
  • 1,528
  • 1
  • 15
  • 31
  • Do you try to implement this example (https://developers.google.com/gmail/api/quickstart/quickstart-java#step_1_enable_the_gmail_api) ? – d.danailov Sep 13 '14 at 06:12
  • Yes. it is simple enough. But still does not explain why the GooglaApiCient returns an unusable token. – TalMihr Sep 18 '14 at 22:06
  • Just as a data point, `GoogleAuthUtil` works fine for me in using the Gmail API to send email from a service on Jelly Bean and KitKat. I'm using the REST API directly (i.e. via `HttpURLConnection`) instead of the Java client library, but that should be independent of the token acquisition. I was getting your 403 for a while until I set up the Client ID for Android application properly but it's been fine after that with refresh handled automatically. One possible place to go wrong that you don't show is handling `UserRecoverableAuthExtension` on the `getToken()` call. – rhashimoto Oct 25 '14 at 00:54
  • Any special way to set the client ID. I've done it multiple times and still got the same 403 error. UserRecoverableAuthExtension is handled. – TalMihr Oct 25 '14 at 08:51
  • Step 2 of [this page](http://aboutyusata.blogspot.com/2014/08/android-single-signin-with-google.html) describes what worked for me. You can also try using the token on your development machine, e.g. with curl: `curl -v -H "Authorization: Bearer ya29.pwAy..." https://www.googleapis.com/gmail/v1/users/me/messages`. This will work for an hour after the token is generated. Put @rhashimoto in any reply if you want me to see it. – rhashimoto Oct 25 '14 at 16:35
  • I am also facing same issue. Can u please let me know how you solve it? – Nivedh Feb 10 '16 at 07:35
  • What should i do more after following https://developers.google.com/gmail/api/quickstart/android – Nivedh Feb 10 '16 at 10:13

4 Answers4

6

Although it's not described clearly, the problem is that the token obtained via GoogleAuthUtil.getToken() is cached locally and may expire. The 403 error you're receiving is due to an expired token. The correct way to handle this situation is to call GoogleAuthUtil.clearToken() to remove the locally cached token, and then call GoogleAuthUtil.getToken() to get a new one.

Alternatively, you can keep track of the last time you requested a token, and if it's been greater than an hour (the default expiry time for these tokens) do the clearToken + getToken calls pre-preemptively.

Eric Koleda
  • 12,420
  • 1
  • 33
  • 51
  • So I must be doing something terribly wrong because even if I request a new token with GoogleAuthUtil.getToken() and then clear it with GoogleAuthUtil.clearToken() and then request a new one, the new one still does not work (403). – TalMihr Sep 08 '14 at 21:46
  • Did you manage to connect with the Gmail API using the GoogleAuthUtil? It would be lovely if you can share your code. I may be totally off no? – TalMihr Sep 08 '14 at 21:47
  • Here are the token details: { "issued_to": "608941808256-43vtfndets79kf5hac8ieujto8837660.apps.googleusercontent.com", "audience": "608941808256-43vtfndets79kf5hac8ieujto8837660.apps.googleusercontent.com", "scope": "https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/gmail.modify", "expires_in": 3589, "access_type": "offline" } – TalMihr Sep 08 '14 at 22:03
  • As you can see it has not been expired before I make a call to the Gmail API (403). Thanks – TalMihr Sep 08 '14 at 22:05
  • Can you post snippets of the code you are using to do this? – Eric Koleda Sep 09 '14 at 13:12
4

That error message is deceptive, I believe it also happens when the developer project credentials client isn't correct. For example you picked "web application" when really you want "installed application".

Confirm you're correctly following instructions from: https://developers.google.com/accounts/docs/OAuth2

(Should be "installed application", etc.)

Can you post the oauth client info you have from the developers console? (Type and any other non-confidential info in there, etc.)

Eric D
  • 6,901
  • 1
  • 15
  • 26
  • Created an installed application (android) withe deep linking. Sha1 and package verified. The same clienr id works well with google plus API. Getting the feeling that this API is not designed to talk to Android – TalMihr Sep 04 '14 at 16:57
  • The API is client/platform agnostic, it should work on Android as well as any other Google API. Not sure what the problem is here, hopefully someone watching the google-oauth or google-oauth-java-client tags can provide some insight then. – Eric D Sep 04 '14 at 18:20
  • Thanks. Ill keep trying to figure out whats wrong. Problem is I don't see many Gmail API Android users around to get a good feedback on someone who actually got it working. – TalMihr Sep 04 '14 at 18:36
  • I can now confirm that any access token received from using GoogleAuthUtil class or AccountManager class will not work with the Gmail API. On the other hand, requesting a token through a WebView with a Client ID set to "Other" in the API Console will work. The problem is that the token is short lived. And now I am facing with a new problem. How to refresh the token without popping op a dialog. – TalMihr Sep 06 '14 at 21:28
  • Seems from http://stackoverflow.com/questions/25697011/handling-expired-access-token-in-android-without-user-concent that this is fixed, right? (With credit to Noam Wies as well.) – Eric D Sep 08 '14 at 17:03
  • I think is actually a workaround rather than a fix. It will work that way but still a valid token must be provided from the GoogleAuthUtil as well. And its not. – TalMihr Sep 09 '14 at 05:00
0

You need to set up your Android app key in Google Dev Console.

  1. Choose your project, select API & Auth, then click Credentials
  2. Create new client id (though it has other client ids)
  3. Select installed app -> android
  4. Fill in your package name and SHA1 correctly
  5. Create new Key (though it has other client keys)
  6. Select Android key
  7. Fill in the SHA1;packageName like this: 45:B5:E4:6F:36:AD:0A:98:94:B4:02:66:2B:12:17:F2:56:26:A0:E0;com.example

Your problem will be automatically solved. Be sure to create client id and key with both your debug keystore and release keystore.

Wesley
  • 4,084
  • 6
  • 37
  • 60
-3

Well here's the deal. So far Tokens given by GoogleAuthUtil && AccountManager do not work with the Gmail API. Don't know if it's a Google thing or not but my solution is this:

Create a Client Id (Applicaion->Other) in the API console. Use the Client Id & Client secret to obtain an Access Token through a WebView. Save the result Refresh Token. Now whenever you want to refresh the Access Token use this request:

    httpClient = new DefaultHttpClient();
    httpPost = new HttpPost(address);
    params.add(new BasicNameValuePair("refresh_token", token));
    params.add(new BasicNameValuePair("client_id", client_id));
    params.add(new BasicNameValuePair("client_secret", client_secret));
    params.add(new BasicNameValuePair("grant_type", "refresh_token"));
    httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
    httpPost.setEntity(new UrlEncodedFormEntity(params));
    HttpResponse httpResponse = httpClient.execute(httpPost);
    HttpEntity httpEntity = httpResponse.getEntity();
    is = httpEntity.getContent();

Works for me. Hope That in the future a valid token will be provided with the GoogleAuthUtil.getToken() option.

TalMihr
  • 1,528
  • 1
  • 15
  • 31