【发布时间】:2015-07-24 20:54:06
【问题描述】:
我正在尝试通过服务帐户为 google 的存储 api 获取 2 腿 oauth2 访问令牌。
相关文档包含在此处: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
我首先尝试通过他们的 HTTP/REST api 获取令牌。我最终放弃了无法通过以下详细信息的 400 响应:
{ "错误" : "invalid_grant" }
然后我转向推荐的方法:使用 java Google api 客户端库(我正在使用 scala)。
val credentialBuilder = new GoogleCredential.Builder()
.setTransport(GoogleNetHttpTransport.newTrustedTransport())
.setJsonFactory(JacksonFactory.getDefaultInstance())
.setServiceAccountId(Configuration.GoogleAPI.ServiceAccount.email)
.setServiceAccountPrivateKeyFromP12File(new File(Configuration.GoogleAPI.ServiceAccount.pkcs12))
.setServiceAccountScopes(Collections.singleton(StorageScopes.DEVSTORAGE_FULL_CONTROL))
def updateToken = {
val credential = credentialBuilder.build()
credential.refreshToken()
// ... do stuff here with token
}
运行上述程序,我得到一个 TokenResponseException,其有效负载与我直接访问 REST api 时遇到的错误相同。 400 错误请求,invalid_grant 错误。
做一些研究(在 stackoverflow 和其他地方),我发现这个错误消息的最常见原因是:
1) 本地时钟未与 Google 的服务器同步。当我使用 REST api 时,我什至怀疑这一点,因为我以前在其他服务中遇到过这个问题。不过,我很确定这不是时钟问题,因为我反复将时钟与外部 ntp 服务器同步:
sudo ntpdate -s ntp.ubuntu.com
2) 导致此错误的另一个常见原因是服务帐户客户端 ID 设置不正确。大多数人将其设置为他们的服务帐户客户 ID(以“apps.googleusercontent.com”结尾)而不是他们的服务帐户客户电子邮件。很明显这不是问题,因为我正确指向了电子邮件(文档指示了这一点,所以我按照说明进行操作),以“@developer.gserviceaccount.com”结尾。
我被困住了。我检查了用户文档、javadocs、各种论坛。错误消息不是很有帮助(可能是这样设计的,因为它是一个安全端点)。
还有哪些其他可能导致此错误的原因?如何获取我的服务帐号访问令牌?
【问题讨论】:
-
我遇到了同样的问题。你有想过这个吗?
标签: google-oauth google-api-java-client