4

My service account scopes are : https://apps-apis.google.com/a/feeds/user/ and DriveScope.DRIVE

I authorized this same scope in "Manage third party OAuth Client access" in domain settings for my service account Id.

I use the java client of the provisioning api.

I build my credentials with the google oauth client with a GoogleCredential.Builder :

credBuilder.setTransport(HTTP_TRANSPORT)
        .setJsonFactory(JSON_FACTORY)
        .setServiceAccountId(config.serviceAccountId)
        .setServiceAccountPrivateKeyFromP12File(new File(config.keyFilePath))
        .setServiceAccountScopes(SCOPES);
        .setServiceAccountUser("admin.of.my@domain.com")

I try to authorize my request to the provisioning api with

userService = new UserService(config.repositoryId);
userService.setOAuth2Credentials(oAuthCredentials);

where oAuthCredentials are my previously built Service credentials.

With that configuration i can access files and collections from the Google Drive of any user of my domain. But i can't acces the list of users of my domain with those credentials.

If i dont specify the service account user, it doesn't work either

Here is the stack trace i get :

com.google.gdata.util.ServiceForbiddenException: You are not authorized to access this API.
<HTML>
<HEAD>
<TITLE>You are not authorized to access this API.</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>You are not authorized to access this API.</H1>
<H2>Error 403</H2>
</BODY>
</HTML>
at com.google.gdata.client.http.HttpGDataRequest.handleErrorResponse(HttpGDataRequest.java:605)
at com.google.gdata.client.http.GoogleGDataRequest.handleErrorResponse(GoogleGDataRequest.java:564)
at com.google.gdata.client.http.HttpGDataRequest.checkResponse(HttpGDataRequest.java:560)
at com.google.gdata.client.http.HttpGDataRequest.execute(HttpGDataRequest.java:538)
at com.google.gdata.client.http.GoogleGDataRequest.execute(GoogleGDataRequest.java:536)
at com.google.gdata.client.Service.getFeed(Service.java:1135)
at com.google.gdata.client.Service.getFeed(Service.java:998)
at com.google.gdata.client.GoogleService.getFeed(GoogleService.java:645)
at com.google.gdata.client.Service.getFeed(Service.java:1017)
at com.google.gdata.client.appsforyourdomain.AppsForYourDomainService.getFeed(AppsForYourDomainService.java:137)
at foo.bar.baz.eci.gdrive.service.BaseService$1.doTry(BaseService.java:125)
at foo.bar.baz.eci.gdrive.service.BaseService$1.doTry(BaseService.java:1)
at foo.bar.baz.eci.gdrive.service.backoff.BackoffRequest.execute(BackoffRequest.java:50)
at foo.bar.baz.eci.gdrive.service.BaseService.getFeedWithBackoff(BaseService.java:129)
at foo.bar.baz.eci.gdrive.service.BaseService.retrieveAllEntries(BaseService.java:90)
at foo.bar.baz.eci.gdrive.service.GappsUserService.getAllUserFeed(GappsUserService.java:57)
at foo.bar.baz.eci.gdrive.GdriveContentProviderFactory.doDiscover(GdriveContentProviderFactory.java:67)
... 19 more

And the logging from the client lib :

21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest setPrivateHeader
PLUS FIN: Authorization: <Not Logged>
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest setPrivateHeader
PLUS FIN: Authorization: <Not Logged>
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest setPrivateHeader
PLUS FIN: Authorization: <Not Logged>
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest setHeader
PLUS FIN: User-Agent: gdocsRepo GData-Java/1.47.1(gzip)
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest setHeader
PLUS FIN: User-Agent: gdocsRepo GData-Java/1.47.1(gzip)
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest setHeader
PLUS FIN: User-Agent: gdocsRepo GData-Java/1.47.1(gzip)
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest setHeader
PLUS FIN: Accept-Encoding: gzip
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest setHeader
PLUS FIN: Accept-Encoding: gzip
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest setHeader
PLUS FIN: Accept-Encoding: gzip
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest setHeader
PLUS FIN: GData-Version: 1.0
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest setHeader
PLUS FIN: GData-Version: 1.0
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest setHeader
PLUS FIN: GData-Version: 1.0
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
FIN: 403 You are not authorized to access this API.
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
FIN: 403 You are not authorized to access this API.
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
FIN: 403 You are not authorized to access this API.
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Content-Encoding: gzip
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Content-Encoding: gzip
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Content-Encoding: gzip
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Content-Length: 151
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Content-Length: 151
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Content-Length: 151
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: null: HTTP/1.1 403 You are not authorized to access this API.
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: null: HTTP/1.1 403 You are not authorized to access this API.
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: null: HTTP/1.1 403 You are not authorized to access this API.
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Expires: Wed, 21 Nov 2012 14:17:37 GMT
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Expires: Wed, 21 Nov 2012 14:17:37 GMT
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Expires: Wed, 21 Nov 2012 14:17:37 GMT
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: X-XSS-Protection: 1; mode=block
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: X-XSS-Protection: 1; mode=block
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: X-XSS-Protection: 1; mode=block
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: X-Frame-Options: SAMEORIGIN
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: X-Frame-Options: SAMEORIGIN
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: X-Frame-Options: SAMEORIGIN
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Date: Wed, 21 Nov 2012 14:17:37 GMT
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Date: Wed, 21 Nov 2012 14:17:37 GMT
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Date: Wed, 21 Nov 2012 14:17:37 GMT
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Content-Type: text/html; charset=UTF-8
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Content-Type: text/html; charset=UTF-8
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Content-Type: text/html; charset=UTF-8
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Server: GSE
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Server: GSE
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Server: GSE
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: X-Content-Type-Options: nosniff
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: X-Content-Type-Options: nosniff
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: X-Content-Type-Options: nosniff
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Cache-Control: private, max-age=0
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Cache-Control: private, max-age=0
21 nov. 2012 15:17:37 com.google.gdata.client.http.HttpGDataRequest execute
PLUS FIN: Cache-Control: private, max-age=0
Jerome
  • 2,104
  • 1
  • 17
  • 31

2 Answers2

1

After investigation it seems that getting a 403 error happens if the account that is set in .setServiceAccountUser("admin.of.my@domain.com") is not a "Super Admin" of the domain.

However in the case above "admin.of.my@domain.com" is indeed a Super Admin of the domain. Also the code works well with any other Super Admin of the domain which leads to believe that there is something wrong with the account "admin.of.my@domain.com" in particular.

If this happens to anyone else - a.k.a. an account set as "Super Admin" which does not work to access Admins-only APIs through Service Accounts - make sure you let us know in the comments below and we'll investigate further if this impacts lots of people.

Nicolas Garnier
  • 12,134
  • 2
  • 42
  • 39
  • read-only acces is all I need. I'll give you some feedback as soon as i have tested that. – Jerome Nov 21 '12 at 08:57
  • I've just tested with the scopes you've given me. My full list of scopes is : `https://apps-apis.google.com/a/feeds/group/#readonly,https://apps-apis.google.com/a/feeds/user/#readonly,https://docs.google.com/feeds/,https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/userinfo.email`. I receive a TokenResponseException with `invalid_scope` as error during the `Credential.refreshToken` method invokation – Jerome Nov 21 '12 at 09:14
  • Indeed there sem to be issues w/ using service accounts and these scopes as they don't seem to be recognized... I'll work with our team to try to get this fixed. In the mean time if all you need is read-only access to the list of users you can also use the Google Apps Profiles API. I checked and it works fine in that scenarion. Updating the answer. – Nicolas Garnier Nov 21 '12 at 13:04
  • Glad i've found a bug. Should i report it somewhere ? How can I have information about this problem state ? Thank you for your time – Jerome Nov 21 '12 at 13:06
  • Unfortunately, i need access to the users list and the group list. – Jerome Nov 21 '12 at 13:10
  • Hey Jerome, actually this is weird, I just tested with the read+write scope for user provisioning https://apps-apis.google.c‌​om/a/feeds/user/ and things seemed to wirk fine (it was supposed to be disabled in the past). It seems to me that using https://apps-apis.google.c‌​om/a/feeds/user/#readonly does not work but https://apps-apis.google.c‌​om/a/feeds/user/ works fine could you tell me why it was not working for you? – Nicolas Garnier Nov 21 '12 at 13:11
  • Here is what I did: used the access token generated by the OAuth 2 service accounts by doing: `credential.refreshToken();credential.getAccessToken();` then used it in a request to the Provivionning API and it worked fine – Nicolas Garnier Nov 21 '12 at 13:13
  • OK forget about the #readonly scopes they seem to not be working (and I'll investigate) However I was able to successfully do requests to the Groups and the Users endpoints of the provisioning API using service accounts. I've got the access token from the code and then used it in a request manually. Now all we need to do is figure out how to make this work using the client libraries :) – Nicolas Garnier Nov 21 '12 at 13:25
  • It does not work for me, but i have more info for you. First, if I use the group feed scope, i get a 400 bad request, invalid_scope. If I remove this scope, it seems i get a access token, but i get a 403 when i try to get the user feed. – Jerome Nov 21 '12 at 13:29
  • Groups had a type by the way, it needed an 's' I updated the docs :) There was a typo on that document: https://developers.google.com/google-apps/marketplace/manifest#supported_scopes – Nicolas Garnier Nov 21 '12 at 13:33
  • OK great now it would be great if we could get more info on what the client library is doing now. I'm investigating the code there might be a bug... The OAuth 2 support for the older GData client lib is a bit 'experimental' – Nicolas Garnier Nov 21 '12 at 13:37
  • OK not sure yet. But could you try doing this: before the line `userService.setOAuth2Credentials(oAuthCredentials);` do: `oAuthCredentials.refreshToken();` I'm just making sure an access token gets generated the GData client lib might not do refresh automatically. – Nicolas Garnier Nov 21 '12 at 13:38
  • I 'm doing this already. The token is created but i get 403. BTW i invited u to a hangout so we stop spamming SO =) – Jerome Nov 21 '12 at 13:41
  • (sorry I'm not really presentable for a hangout :D) The thing is now we need to go deeper, we need to see what the request the client library is sending looks like. I'm not really knowledgable with the older GData client but there should be a way to enable logging at the HTTP level. – Nicolas Garnier Nov 21 '12 at 13:51
  • Also try the following: print a generated access token and try to use it on the OAuth 2 playground: https://developers.google.com/oauthplayground/ for example trying to do a GET request to: https://apps-apis.google.com/a/feeds/group/2.0/ – Nicolas Garnier Nov 21 '12 at 13:51
  • I still get a 403 when i'm in the OAuth2 playground – Jerome Nov 21 '12 at 13:58
  • Ah! :) Is there an error message that goes with it? You could copy paste the ful HTTP request and response in your question too. – Nicolas Garnier Nov 21 '12 at 14:02
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/19891/discussion-between-jerome-and-nivco) – Jerome Nov 21 '12 at 14:24
0

Now provisioning APIs have been deprecated as of 15th of May 2013. They have introduced new set of APIs called Directory APIs which solves your problem.

Srikanth P Vasist
  • 1,327
  • 2
  • 14
  • 26