3

我需要实现以下场景:

  1. 用户使用他或她的 Google 凭据登录。
  2. 此后,我的应用程序会检查此用户是否在使用 Google Apps。
  3. 如果他或她是,我的应用程序会读取同一 Google Apps 域 ( com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload#getHostedDomain) 中的所有活动用户。

它类似于 Facebook 上的“寻找你的朋友”功能。在这种情况下,我想找到所有使用同一 Google Apps 域的人。

是否有可能(技术上和使用条款)?

更新 1(28.08.2017 20:00 MSK):

我尝试使用访问令牌(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 MSK):

我尝试使用API Explorer获取用户列表。

截图 1

我得到了403错误。详情如下。

截图 2

要求:

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 MSK):

最后,我设法摆脱了身份验证和授权错误(在 G Suite 应用程序的测试安装中)。

但是,现在以下调用返回一个空的用户列表(没有错误)。

val directory = Directory.Builder(
        NetHttpTransport(),
        JacksonFactory.getDefaultInstance(),
        credential)
        .setApplicationName("Google Auth Test")
        .build()
val users = directory.users().list()
4

3 回答 3

1

您需要从用户那里获得足够的权限才能获取域中所有用户的列表。此外,它仅在登录用户是域的超级管理员时才有效。

您可以在此处获取权限列表。

于 2017-09-01T09:58:39.457 回答
1

这个问题与Google API/get directory contacts相关

我在这里发布一个答案,因为这个答案对谷歌更友好:

即使没有管理员权限,Admin Directory Users:list资源也允许列出公司目录。

只要确保您设置viewTypedomain_public,您就可以开始了:

https://www.googleapis.com/admin/directory/v1/users?customer=my_customer&viewType=domain_public

一个范围https://www.googleapis.com/auth/admin.directory.user.readonly应该足够了。

于 2019-12-30T22:04:36.473 回答
0

检查此文档以检索同一域中的所有用户,使用以下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
于 2017-08-23T17:45:43.600 回答