【问题标题】:Correct way to use a Google Apps Marketplace service account to connect to Gmail IMAP and other services使用 Google Apps Marketplace 服务帐户连接到 Gmail IMAP 和其他服务的正确方法
【发布时间】:2014-01-21 00:28:28
【问题描述】:

我们的 Marketplace 应用的一项功能是通过 IMAP 访问用户的 Gmail 帐户。我们正在使用 google-api-java-client 和 google-oauth-java-client 库和类似于this example in the java-gmail-imap project 的代码如下:

GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
    .setJsonFactory(JSON_FACTORY)
    .setServiceAccountId(SERVICE_ACCOUNT_ID)
    .setServiceAccountScopes(Arrays.asList(GMAIL_SCOPE))
    .setServiceAccountPrivateKey(PRIVATE_KEY)
    .setServiceAccountUser(emailAddress)
    .build();
credential.refreshToken();

然后我们使用基于https://code.google.com/p/google-mail-oauth2-tools 示例的代码来建立 IMAP 连接,例如

IMAPStore imapStore = OAuth2Authenticator.connectToImap("imap.googlemail.com",
    993, emailAddress, credential.getAccessToken(), false);

在大多数情况下,这似乎可以正常工作,但是我们看到,对于少量但大量的请求,refreshToken() 对 Google 的调用失败并出现 HTTP 500 错误和 HTML 响应,其中 JSON 会通常会被退回,例如

<p class="large"><b>500.</b> <ins>That's an error.</ins></p>
<p class="large">The server could not process your request.
<ins>That's all we know.</ins></p>

Google 的一位开发者倡导者告知我们,服务帐户不支持刷新令牌,我们应该使用this example 中的方法。

然而,似乎没有调用refreshToken然后accessToken没有填充在凭证对象上,然后当我们调用OAuth2Authenticator.connectToImap时这会导致NullPointerException p>

GoogleCredential 的源代码看来,executeRefreshToken() 似乎被覆盖以处理服务帐户,即它不执行刷新,它只是请求一个新令牌,然后Credential 中的这段代码然后处理填充访问令牌:

TokenResponse tokenResponse = executeRefreshToken();
if (tokenResponse != null) {
    setFromTokenResponse(tokenResponse); ....

我们不确定是否需要将对 refreshToken() 的调用包含在重试循环中以解决间歇性 500 错误,或者我们是否需要对代码进行其他更改以遵循针对这种情况的推荐方法。

谁能给点建议?

【问题讨论】:

    标签: google-apps-marketplace google-oauth-java-client


    【解决方案1】:

    我在生产中使用java-gmail-imap example 代码(但它仅用于在我们的大学门户中显示收件箱,没有太多交互需要我重复使用相同的刷新令牌)。

    根据您的使用情况,我想知道在您的情况下是否会出现某种限制(我在 Gmail can occasionally throttle access 的地方读过)。

    我在其他地方看到 Google API 谈论使用 exponential backoff algorithm 进行重试。

    在将 OAuth 2.0 的使用与其他 Google 服务 API 和 Gmail 进行比较时,您必须小心谨慎。 Gmail 的特殊之处在于它使用 XOAUTH2。也就是说,我已经看到其他似乎需要refreshToken call 的 Google API。文档有点不清楚,并说诸如“Refresh the access token, if necessary”之类的东西(正如您所说,如果没有这一步,它似乎无法工作,但我还没有通过 credential.setRefreshToken(String refreshToken) 对重新使用刷新令牌进行任何实验))。

    我很想听听你的进展。

    【讨论】:

    • 谢谢。目前我们正在使用我们自己的重试循环。即如果getAccessToken() 在调用refreshToken() 后返回null,那么我们会重试几次,重试之间的延迟会增加。从我们的日志中,我们确实看到很大一部分最初失败的请求在第一次或第二次重试后成功,所以这有点帮助。 IMAP 访问是目前我们使用的唯一需要以这种方式访问​​令牌的 Google 服务。我们确实也看到了某些用户的 Gmail 限制邮件,但那是在身份验证之后。如果我发现更多信息,我一定会告诉你的。
    猜你喜欢
    • 1970-01-01
    • 2013-03-28
    • 1970-01-01
    • 2016-01-21
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多