Можно ли получить всех пользователей из одного домена Служб Google?
Мне нужно реализовать следующий сценарий:
- Пользователь входит в систему со своими учетными данными Google.
- После этого мое приложение проверяет, использует ли этот пользователь Google Apps.
- Если это так, мое приложение считывает всех активных пользователей в одном домене Служб Google (
com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload#getHostedDomain
).
Это похоже на функцию "Найти друзей" на Facebook. В этом случае я хочу найти всех людей, которые используют один и тот же домен Служб Google.
Возможно ли это сделать (как технически, так и в отношении условий их использования)?
Обновление 1 (28.08.2017, 20:00 мск):
Я попытался получить список всех пользователей, использующих токен доступа (gIdToken.payload.accessTokenHash
во фрагменте кода ниже):
internal open fun createJsonFactory(): JsonFactory = JacksonFactory.getDefaultInstance()
internal open fun createTransport(): HttpTransport = GoogleNetHttpTransport.newTrustedTransport()
internal open fun createVerifier(httpTransport: HttpTransport, jsonFactory: JsonFactory): GoogleIdTokenVerifier {
return GoogleIdTokenVerifier.Builder(httpTransport, jsonFactory)
.setAudience(listOf(clientId))
.build()
}
val idToken = req.queryParams("idtoken")
val httpTransport = createTransport()
val jsonFactory = createJsonFactory()
val verifier = createVerifier(httpTransport, jsonFactory)
val gIdToken = verifier.verify(idToken)
if ((gIdToken != null) && (gIdToken.payload != null)) {
val credential = GoogleCredential().setAccessToken(gIdToken.payload.accessTokenHash)
val directory = Directory.Builder(httpTransport, jsonFactory, credential)
.setApplicationName("Google Auth Test")
.build()
try {
directory.users().list().setCustomer(gIdToken.payload.subject).execute()
}
catch (ex:Throwable) {
ex.printStackTrace()
}
}
Когда я бегу directory.users().list().setCustomer(gIdToken.payload.subject).execute()
Я получаю следующую ошибку:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
"code" : 401,
"errors" : [ {
"domain" : "global",
"location" : "Authorization",
"locationType" : "header",
"message" : "Invalid Credentials",
"reason" : "authError"
} ],
"message" : "Invalid Credentials"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:146)
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:321)
Я использую следующие библиотеки Google:
<dependency>
<groupId>google-api-services</groupId>
<artifactId>admin-directory_v1</artifactId>
<version>1.22.0</version>
</dependency>
<dependency>
<groupId>com.google.gdata</groupId>
<artifactId>core</artifactId>
<version>1.47.1</version>
</dependency>
Как я могу исправить ошибку выше?
Обновление 2 (29.08.2017 11:39 MSK): пробовал использовать Контакты API
Попытка 1: фид API контактов
import com.google.gdata.data.extensions.ContactFeed
fun readUsers2(gIdToken:GoogleIdToken, httpTransport: HttpTransport, jsonFactory:JsonFactory) {
val credential = GoogleCredential().setAccessToken(gIdToken.payload.accessTokenHash)
val service = ContactsService("Google Auth Test")
service.setOAuth2Credentials(credential)
val feedUrl = URL("https://www.googleapis.com/auth/contacts.readonly")
val resultFeed: ContactFeed = service.getFeed(feedUrl, ContactFeed::class.java)
}
Результат: исключение "Нераспознанный тип контента: текст / обычный" вcom.google.gdata.client.Service#parseResponseData(com.google.gdata.data.ParseSource, com.google.gdata.wireformats.input.InputProperties, java.lang.Class<E>)
, см. заявление броска ниже.
private <E> E parseResponseData(ParseSource source, InputProperties inputProperties, Class<E> resultType) throws IOException, ServiceException {
Preconditions.checkNotNull("resultType", resultType);
AltFormat inputFormat = null;
String alt = inputProperties.getQueryParameter("alt");
if (alt != null) {
inputFormat = this.altRegistry.lookupName(alt);
}
if (inputFormat == null) {
inputFormat = this.altRegistry.lookupType(inputProperties.getContentType());
if (inputFormat == null) {
throw new ParseException("Unrecognized content type:" + inputProperties.getContentType());
}
}
Попытка 2: запрос API контактов
fun readUsers3(gIdToken:GoogleIdToken, httpTransport: HttpTransport, jsonFactory:JsonFactory) {
val credential = GoogleCredential().setAccessToken(gIdToken.payload.accessTokenHash)
val service = ContactsService("Google Auth Test")
service.setOAuth2Credentials(credential)
val feedUrl = URL("https://www.googleapis.com/auth/contacts.readonly")
val query = Query(feedUrl)
val resultFeed = service.query(query, ContactFeed::class.java)
}
Результат: то же исключение, что и при попытке 2.
Обновление 3 (29.08.2017 13:04 мск):
Я попытался получить список пользователей, используя API Explorer.
Я получил 403
ошибка. Подробности приведены ниже.
Запрос:
GET https://www.googleapis.com/admin/directory/v1/users?domain={MYDOMAIN}&fields=users(emails%2Cid%2Cname)&key={YOUR_API_KEY}
Отклик:
403
- Show headers -
{
"error": {
"errors": [
{
"domain": "global",
"reason": "forbidden",
"message": "Not Authorized to access this resource/api"
}
],
"code": 403,
"message": "Not Authorized to access this resource/api"
}
}
Обновление 4 (30.08.2017 13:19 мск):
Наконец, мне удалось избавиться от ошибок аутентификации и авторизации (в тестовой установке приложения G suite).
Однако теперь следующие вызовы возвращают пустой список пользователей (без ошибок).
val directory = Directory.Builder(
NetHttpTransport(),
JacksonFactory.getDefaultInstance(),
credential)
.setApplicationName("Google Auth Test")
.build()
val users = directory.users().list()
2 ответа
Вам необходимо получить достаточные разрешения от пользователя, чтобы получить список всех пользователей в домене. Более того, он будет работать только в том случае, если вошедший в систему пользователь является супер-администратором домена.
Вы можете получить список разрешений здесь.
Этот вопрос связан с Google API/ получить контакты каталога
Я публикую здесь ответ, так как этот более удобен для Google:
Ресурс Admin Directory Users: list позволяет отображать каталог компании даже без прав администратора.
Просто убедитесь, что вы установили viewType
к domain_public
и тебе хорошо идти:
https://www.googleapis.com/admin/directory/v1/users?customer=my_customer&viewType=domain_public
Объем https://www.googleapis.com/auth/admin.directory.user.readonly
должно хватить.
Проверьте эту документацию, чтобы получить всех пользователей в одном домене, используйте следующие GET
запросить и включить авторизацию, описанную в разделе Авторизация запросов. Для удобства чтения этот пример использует возврат строки:
GET https://www.googleapis.com/admin/directory/v1/users
?domain=primary domain name&pageToken=token for next results page
&maxResults=max number of results per page
&orderBy=email, givenName, or familyName
&sortOrder=ascending or descending
&query=email, givenName, or familyName:the query's value*
Для свойств запроса и ответа вы можете использовать метод Users: list, в котором он извлекает разбитый на страницы список либо удаленных пользователей, либо всех пользователей в домене. Этот запрос требует авторизации как минимум с одной из следующих областей ( подробнее об аутентификации и авторизации).
https://www.googleapis.com/auth/admin.directory.user.readonly
https://www.googleapis.com/auth/admin.directory.user