API каталогов Google возвращает Not Authorized при вызове users().list().execute()

Мне нужно прочитать список пользователей (и групп) из моего домена Google.

Поэтому я зашел в свою консоль API Google, включил Admin SDK и создал аккаунт службы для вызова API Google. Я использую следующие библиотеки Google

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

Мой код

     /*
     * 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();

И я получаю это в последней строке

Ошибка

{
  "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)

Если я раскомментирую закомментированную строку (.setServiceAccountUser("[email protected]")), я получу другую ошибку

    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)

Моя учетная запись ([email protected]) является суперадминистратором. Я подозреваю, что сервисному аккаунту должен быть предоставлен доступ к области пользовательского API. Но я не могу найти, где я могу предоставить этот доступ. У меня есть классический режим пользовательского интерфейса моего Google CPanel. И у меня нет страницы «Управление доступом к клиентскому API» в дополнительных инструментах.

Дополнительные инструменты

Также я не уверен, что мне следует использовать в качестве имени приложения в .setApplicationName("Test").

Спасибо за любую помощь


person dmitry747    schedule 02.09.2013    source источник


Ответы (4)


вы можете перейти к настройкам «безопасности» в консоли администратора (admin.google.com/AdminHome?chromeless=1&pli=1#SecuritySettings:); затем нажмите «Дополнительные настройки» > «Управление доступом стороннего клиента OAuth». После этого сопоставьте свой идентификатор клиента (сгенерированный из appconsole code.google.com/apis/console в разделе «Доступ к API для oath2») и «Одна или несколько областей API». Используйте области действия, разделенные запятыми, как указано здесь. Для каталога Google вы можете использовать https://www.googleapis.com/auth/admin.directory.group,https://www.googleapis.com/auth/admin.directory.user

Надеюсь после этого заработает :)

person Bijay Mahato    schedule 05.09.2013
comment
У меня классическая консоль администратора. Страницы находятся в других местах. - person dmitry747; 05.09.2013
comment
я использую пробную учетную запись и не получаю эту опцию, просто говорит «Управление доступом клиента OAuth». это из-за пробной версии или требуется какая-то настройка - person heyyan khan; 06.08.2014

У меня была точно такая же проблема, и я застрял на этот образец

Что мне помогло: 1/ я не делегировал полномочия на уровне домена вашему сервисному аккаунту, как предложил Джей Ли. Но после этого у меня все еще была проблема. 2/ Затем, согласно это сообщение, вызов setServiceAccountUser([email protected]) является обязательным.

person oprami    schedule 29.09.2014

Google Directory API работает с учетной записью службы Compute Engine по умолчанию, вам не нужно настраивать Google Диск для всего домена. Единственное: вы должны установить serviceAccountUser, который не поддерживается в учетных данных на основе JSON. Так что вы можете

  • используйте ключи P12
  • учетные данные пользователя JSON с обходным путем:

сделать копию учетных данных:

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

Для моего пробного аккаунта G Suite это работает!

person Grigory Kislin    schedule 18.02.2017

Вы можете предоставить сервисному аккаунту доступ к определенным областям в панели управления, как описано в домене Google Диска. -широкая документация. Вместо этого просто используйте области Admin SDK.

Имя приложения используется в заголовке запросов User-Agent и поэтому не слишком важно, просто используйте имя вашего приложения и, возможно, версию.

person Jay Lee    schedule 02.09.2013
comment
Спасибо за ваш ответ. Я не могу найти это Управление доступом стороннего клиента OAuth. элемент в дополнительных инструментах в моей панели управления, как описано в документе Google Диска. Наверное надо как-то включить? - person dmitry747; 03.09.2013
comment
Инструкции см. на странице support.google.com/a/bin/. answer.py?hl=ru&answer=162106. Похоже, у вас может быть включена новая консоль администратора. - person Jay Lee; 03.09.2013
comment
Я не смог найти эту страницу управления доступом к клиентскому API. Я добавил изображение своих дополнительных инструментов. Наверное надо что-то включить? - person dmitry747; 04.09.2013
comment
Какой выпуск Google Apps вы используете? (EDU, Business, Free/Standard)? - person Jay Lee; 04.09.2013
comment
Я использую Google Apps Partner Edition - person dmitry747; 05.09.2013
comment
Согласно: developers.google.com/admin-sdk/directory/v1 /guides/ в разделе Основные сведения о GAfP не поддерживается. Вы можете попробовать получить доступ к API напрямую в качестве суперадминистратора, используя стандартный OAuth 2.0, но я не верю, что учетные записи служб вам подходят. - person Jay Lee; 05.09.2013
comment
Я перешел на старый API gdata. Этот API, кажется, делает то, что мне нужно. - person dmitry747; 05.09.2013
comment
Спасибо за вашу помощь - person dmitry747; 05.09.2013