如何使用GAE服务帐户调用服务器到服务器的云端点?

时间:2016-07-28 22:27:01

标签: java google-app-engine service-accounts

我们在面向微服务的架构中广泛使用Google Cloud Endpoints(GCE)。所有服务均为Google App Engine。对于面向公众的GAE服务,我们将使用标准的Android OAuth对真实用户进行身份验证。但是,对于非面向用户的服务,我们希望我们的Cloud Endpoints受到保护(不公开),但可以通过默认的GAE服务帐户访问。

例如,内部付款服务可能希望与内部用户服务联系以获取用户的个人资料,使用默认的GAE服务帐户进行身份验证,因此我们不需要在代码中嵌入任何凭据。我们正在使用生成的Java库。

我使用这样的代码用生成的libs初始化服务:

public User createUserService() {    
    AppIdentityCredential credential = new AppIdentityCredential(Lists.newArrayList(OAUTH_EMAIL_SCOPE))
    return new User.Builder(new UrlFetchTransport(), new JacksonFactory, credential)
        .setRootUrl(userServiceRootUrl)
        .build()
}

我们尝试使用 GoogleCredential.getApplicationDefault()并在该凭据对象上设置范围。

从第一个GAE服务调用的目标端点的代码如下:

@Api(
  name      = "user",
  version   = "v1",
  clientIds = Array(Constants.APP_ENGINE_SERVICE_ACCOUNT_CLIENT_ID)
)
class UserEndpoints {
  /**
    * GET /user/:id
    *
    * Get a single user by id
    */
  @ApiMethod(
    httpMethod = HttpMethod.GET,
    path = "user/{id}"
  )
  def find(
    @Named("id") id: Long,
    authUser: GoogleUser
  ): User = {
    if (authUser == null) {
      throw new OAuthRequestException("Must be authenticated to use this endpoint!")
    }
    UserDAO.find(id) getOrElse  {
      throw new NotFoundException("User not found")
    }
  }

上面使用的客户端ID是您可以在GAE服务帐户的JSON密钥文件中找到的客户端ID,如果您已将域范围委派添加到您的服务帐户,则会显示在API凭据控制台中。

我们也尝试过对此进行修改,例如删除User参数,而是在@Api注释上设置 authLevel = AuthLevel.REQUIRED

没有骰子,我们总是会收到这样的错误:

Request URL: https://user-service-dot-foo-dev.appspot.com/_ah/api/user/v1/user/1
Method: user.userEndpoints.find
Error Code: 403
Reason: insufficientAuthorizedParty
Message: Client_id is not allowed

有谁知道 - 我们做错了什么?为什么使用服务帐户保护流量如此困难?

我们希望避免在我们的代码中嵌入凭据,因此请不要回答说我们需要创建一个手动服务帐户。

感谢任何好的建议!我们真的很惊讶与云端点进行服务器到服务器通信是多么困难!

0 个答案:

没有答案