4

I need to read the list of users (and groups) from my google domain.

So I went to my Google APIs Console and enabled Admin SDK and created a Service Account to call Google APIs. I use the following google libraries

  • google-api-services-admin-directory_v1-rev11-1.16.0-rc.jar
  • google-api-client-1.16.0-rc.jar

My code is

     /*
     * Global instance of the JSON factory.
     */
    final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
     /*
      Global instance of the HTTP transport.
     */
        HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();

        Collection<String> scopeList = new ArrayList<>();
        scopeList.add(DirectoryScopes.ADMIN_DIRECTORY_USER);
        scopeList.add(DirectoryScopes.ADMIN_DIRECTORY_GROUP);
        scopeList.add(DirectoryScopes.ADMIN_DIRECTORY_GROUP_MEMBER);

        GoogleCredential credential = new GoogleCredential.Builder()
                .setTransport(httpTransport)
                .setJsonFactory(JSON_FACTORY)
                .setServiceAccountId("[email protected]")
                .setServiceAccountScopes(scopeList)
                .setServiceAccountPrivateKeyFromP12File(new File("/Path/To/KeyFile/nnnnn-privatekey.p12"))
//                .setServiceAccountUser("[email protected]")
                .build();

        Directory admin = new Directory.Builder(httpTransport, JSON_FACTORY, credential)
                .setApplicationName("Test")
                .setHttpRequestInitializer(credential).build();


        Users users = admin.users().list().setDomain("mydomain.org").execute();

And I receive this on the last line

Error

{
  "code" : 403,
  "errors" : [ {
    "domain" : "global",
    "message" : "Not Authorized to access this resource/api",
    "reason" : "forbidden"
  } ],
  "message" : "Not Authorized to access this resource/api"
}
    at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145)
    at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
    at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:312)
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1045)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)

If I uncomment the commented line (.setServiceAccountUser("[email protected]")) then I get a different error

    Exception in thread "main" com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
  "error" : "access_denied"
}
    at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
    at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
    at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
    at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:269)
    at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489)
    at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:217)
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:858)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)

My account ([email protected]) is a super administrator. I suspect the Service Account needs to be granted access for the users API scope. But I can not find where I can grant this access. I have a classic UI mode of my Google CPanel. And I don't have "Manage client API access" page in the Advanced tools.

Advanced tools

Also I'm not sure what I should use as an Application Name at .setApplicationName("Test").

Thanks for any help

4 Answers 4

2

you can go to "security" settings in the admin console (admin.google.com/AdminHome?chromeless=1&pli=1#SecuritySettings:); then click on advance settings > Manage third party OAuth Client access. After this map your client id(generated from appconsole code.google.com/apis/console under API access for oath2) and "One or More API Scopes". Use comma separated scopes as mentioned there. For google directory you can use https://www.googleapis.com/auth/admin.directory.group,https://www.googleapis.com/auth/admin.directory.user

Hope after this it works :)

Sign up to request clarification or add additional context in comments.

2 Comments

I've got the classic admin console. The pages are on other locations.
i am using a trial account and not getting this option, just says 'Manage OAuth Client access'. is it because of the trial or is there some configuration required
2

I had the exact same problem, and was stucked on this sample

What helped me : 1/ I did not Delegate domain-wide authority to your service account, as suggested by Jay Lee. But after that, I still had the problem. 2/ Then, according to this post, the call to setServiceAccountUser([email protected]) is mandatory.

Comments

2

Google Directory API works with Compute Engine default service account, you do not need to setup Google Drive domain-wide. The only thing: you have to set serviceAccountUser, which is not supported in JSON based credentials. So you can

  • use P12 keys
  • user JSON credentials with workaround:

make credential copy:

import static com.google.api.client.googleapis.util.Utils.getDefaultJsonFactory;
import static com.google.api.client.googleapis.util.Utils.getDefaultTransport;

private static final String APPLICATION_NAME = "AnyAppName";

private final List<String> SCOPES = ImmutableList.of(
        DirectoryScopes.ADMIN_DIRECTORY_GROUP_MEMBER, DirectoryScopes.ADMIN_DIRECTORY_USER, DirectoryScopes.ADMIN_DIRECTORY_GROUP);

private Directory service;

@PostConstruct
void init() throws GeneralSecurityException, IOException {
    GoogleCredential credential;
    try (InputStream is = new FileInputStream("./config/client_secret.json")) {
        credential = GoogleCredential.fromStream(is);
    }
    GoogleCredential credentialWithUser = new GoogleCredential.Builder()
            .setTransport(getDefaultTransport())
            .setJsonFactory(getDefaultJsonFactory())
            .setServiceAccountUser("[email protected]")  // <--- mail of domain's admin
            .setServiceAccountId(credential.getServiceAccountId())
            .setServiceAccountScopes(SCOPES)
            .setServiceAccountPrivateKey(credential.getServiceAccountPrivateKey())
            .setServiceAccountPrivateKeyId(credential.getServiceAccountPrivateKeyId())
            .setTokenServerEncodedUrl(credential.getTokenServerEncodedUrl()).build();

    service = new Directory.Builder(getDefaultTransport(), getDefaultJsonFactory(), credentialWithUser).setApplicationName(APPLICATION_NAME).build();
}

 public void members() throws IOException {
    Members members = service.members().list("[email protected]").execute();
    System.out.println(members);
 }

For my trial G Suite account it works!

Comments

1

You can grant the service account access to certain scopes in the Control Panel as explained in the Google Drive domain-wide documentation. Just use Admin SDK scopes instead.

The application name is used in the User-Agent header of requests and so is not overly important, just use your apps name and maybe version.

7 Comments

Thanks for your response. I can not find this "Manage third party OAuth Client access." item in the Advanced tools in my Control Panel as described in the Google Drive doc. Probably I need to enable it somehow?
See instructions at: support.google.com/a/bin/answer.py?hl=en&answer=162106. It sounds like you may have the new admin console enabled.
I couldn't find this "Manage client API access" page. I added a picture of my Advanced tools. Probably I need to enable something?
What edition of Google Apps are you using? (EDU, Business, Free/Standard)?
I'm using Google Apps Partner Edition
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.