通过OAuth 2.0和私钥(即服务帐户)访问Google通讯录Api

时间:2013-01-18 20:51:42

标签: google-api oauth-2.0 gdata-api google-contacts service-accounts

我目前正在通过OAuth 2.0和所谓的服务帐户实施对Google通讯录的访问。为普通用户生成服务帐户,例如“My.Name@gmail.com”。

生成OAuth 2.0凭据的代码是:

public static GoogleCredential getCredentials() throws GeneralSecurityException, IOException {
    GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
            .setJsonFactory(JSON_FACTORY)
            .setServiceAccountId(SingleUserCredentials.SERVICE_ACCOUNT_EMAIL)
            .setServiceAccountScopes("https://www.google.com/m8/feeds")
            .setServiceAccountPrivateKeyFromP12File(new File(SingleUserCredentials.SERVICE_ACCOUNT_PKCS12_FILE_PATH))
            .build();
    credential.refreshToken();
    return credential;
}

然后我尝试通过以下方式检索联系人:

    ContactsService myService = new ContactsService(
            "myApp");

    myService.setOAuth2Credentials(getCredentials());

    URL feedUrl = new URL("https://www.google.com/m8/feeds/contacts/default/full");
    Query myQuery = new Query(feedUrl);
    ContactFeed resultFeed = myService.query(myQuery, ContactFeed.class);
    // Print the results

    for (ContactEntry entry : resultFeed.getEntries()) {
        System.out.println(entry.getName().getFullName().getValue());
        System.out.println("Updated on: " + entry.getUpdated().toStringRfc822());
    }

问题是我的帐户中没有任何一个联系人。 Feed始终为空。没有错误。没有。

通过相同的方法访问Google Apps托管域时,效果很好。

我想知道在使用p12密钥文件和服务帐户时,联系人Api是否支持普通(也称为@ gmail.com)帐户的OAuth 2.0。

3 个答案:

答案 0 :(得分:1)

我自己遇到了同样的问题。

我尝试了设置密钥时收到的电子邮件地址和域管理员的电子邮件地址。

当我使用密钥设置中的电子邮件时,我根本没有收到任何内容 - 没有警告,没有例外,也没有数据。

当我使用域管理员的电子邮件地址时,我收到一个例外:

com.google.api.client.auth.oauth2.TokenResponseException: 400 OK
     [java] {
     [java]   "error" : "invalid_grant"
     [java] }
     [java] Feb 5, 2013 5:16:48 PM com.google.appengine.repackaged.org.apache.http.impl.client.DefaultRequestDirector handleResponse
     [java] WARNING: Authentication error: Unable to respond to any of these challenges: {}
     [java] Feb 5, 2013 5:16:48 PM com.google.apphosting.utils.jetty.JettyLogger warn
     [java] WARNING: /
     [java] java.lang.NullPointerException: No authentication header information

...

所以,我认为域管理员的电子邮件地址不是我需要的。

接下来,在找到此页面之前,我用Google搜索了一段时间:

http://javadoc.google-api-java-client.googlecode.com/hg/1.13.2-beta/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.html

我在那里看到了getServiceAccountUser()。该领域的描述是:

返回应用程序尝试在服务帐户流中模拟的用户的电子邮件地址,如果没有,或者如果不使用服务帐户流,则返回null。

果然,有一个相应的setServiceAccountUser(String)接受您正在使用服务帐户进行模拟的用户的用户名(电子邮件地址)。

我将该字段设置为适当的值,然后我就可以继续了。

回想起来,这一切都是有道理的 - 如果我不提供我正在努力工作的帐户,我就无法提取该帐户的联系人。

答案 1 :(得分:0)

目前无法使用服务帐户访问联系人,因为Google APIs Console的Google API控制台不支持该联系人。

另请参阅:Service Accounts

其次,它只适用于Google托管域名,因为域名管理员必须通过以下流程授予对服务帐户的访问权限:

将域范围的权限委派给您的服务帐户

您现在创建的服务帐户需要被授予访问您要访问的Google Apps域的用户数据的权限。以下任务必须由Google Apps域管理员执行:

  1. 转到Google Apps域的控制面板。该网址应如下所示:“www.google.com/a/cpanel/mydomain.com”

  2. 转到高级工具...>管理第三方OAuth客户端访问权限。

  3. 在客户名称字段中输入服务帐户的客户ID。

  4. 在“一个或多个API范围”字段中,输入应授予您的应用程序访问权限的范围列表。

  5. 单击“授权”按钮。

答案 2 :(得分:0)

我今天遇到了同样的错误,但现在已经放弃使用服务帐户,我认为联系人API目前不支持。所以我在OAuth 1.0中使用Contacts API v3并获得了预期的结果。

 ContactsService contactsService = new ContactsService(APPLICATION_NAME);
 contactsService.setUserCredentials(CLIENT_USERNAME, CLIENT_SECRET);

 URL contactFeedURL = new URL("https://www.google.com/m8/feeds/contacts/default/full");
 Query contactFeedQuery = new Query(contactFeedURL);

 ContactFeed contactFeed = contactsService.getFeed(contactFeedQuery, ContactFeed.class);