是否可以从同一个Google Apps域中获取所有用户?

时间:2017-08-22 08:12:59

标签: google-oauth google-admin-sdk google-directory-api google-shared-contacts google-profiles-api

我需要实现以下场景:

  1. 用户使用其Google凭据登录。
  2. 此后,我的应用程序会检查此用户是否使用Google 的应用程序。
  3. 如果他或她是,我的应用程序会读取同一Google中的所有活跃用户 应用领域(com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload#getHostedDomain)。
  4. 类似于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):尝试使用Contacts API

    尝试1:联系人API Feed

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

    结果:异常“无法识别的内容类型:text / plain”in 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获取用户列表。

    Screenshot 1

    我收到403错误。详情如下。

    Screenshot 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套件app的安装。)

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

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

3 个答案:

答案 0 :(得分:1)

选中此documentation以检索同一域中的所有用户,使用以下GET请求并包含Authorize requests中所述的授权。为了便于阅读,此示例使用行返回:

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方法,它会检索已删除用户或域中所有用户的分页列表。此请求需要至少使用以下范围之一(read more about authentication and authorization)进行授权。

  • https://www.googleapis.com/auth/admin.directory.user.readonly
  • https://www.googleapis.com/auth/admin.directory.user

答案 1 :(得分:1)

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

您可以获取权限列表here

答案 2 :(得分:0)

此问题与Google API/get directory contacts

有关

我在这里发布答案,因为这对Google更友好:

“管理员目录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的范围就足够了。