如何使用 google 服务帐户和 oauth 限制对我的 google 云函数的调用?

How do I limit invocations to my google cloudfunction using a google service account and oauth?

我有一个云函数,我想从目前在 Heroku 上 运行 的 rails 应用调用。我为 rails 应用程序设置了一个服务帐户,并且 could 函数由 HTTP 请求部署和触发。我想将云功能的调用限制在 rails 应用程序中,并计划在 google.

之后的 this documentation 之后使用服务器到服务器的 2-legged OAuth 2.0 ]

不过,当我设置服务帐户时,我需要提供一个范围。根据 available scopes 的列表,唯一引用 Cloud Functions 的范围允许管理云功能,而我希望范围仅涵盖调用。

文档中使用的语言是指用于定义对 Google API 的访问的范围。

关于 this topic 的 Cloud Functions 文档涵盖了几个用例:

  • Securing developer access so that only specific users can invoke the function during testing.

  • Securing function-to-function access so that only authorized functions can invoke your function.

  • Securing end-user access to an application from mobile or web clients.

您的用例是第三个,最终用户身份验证是通过 Google Sign-In and Firebase Authentication 集成的,但这对于限制 HTTP 调用仅允许您的 Heroku 应用程序没有用。

此时应通过检查您的 Cloud Functions 代码中的请求是否来自 Heroku 应用程序来管理解决方法,并拒绝那些不是的请求。

是的,我设法从几个不同的 Google 文档页面拼凑了这个过程,即

  1. https://cloud.google.com/iap/docs/authentication-howto#authenticating_from_a_service_account
    • 错误地指示您 self-sign 您的 JWT,这显然行不通,因为这样任何人都可以签署自己的 JWT 并访问您的云功能
  2. https://cloud.google.com/functions/docs/securing/authenticating#service-to-function
    • 此示例不会告诉您在初始 JWT 声明中设置哪些受众
  3. https://developers.google.com/identity/protocols/OAuth2ServiceAccount#authorizingrequests
    • 错误描述了 JWT 声明内容和签名过程
    • 直接使用服务帐户签名的 JWT 作为承载令牌的 alternate method 不适用于调用云函数,我猜是因为它们不是 google API

这是对我有用的

  1. 使用以下数据编组 JWT。主要技巧是将 aud 设置为 OAuth 端点,将 sub 设置为服务帐户的电子邮件(即使没有用户可模拟),并将 target_audience 设置为 Cloud Function 的 URL(根据文档 #1),但遵循文档 #3 中的一般流程。

    {
      "aud": "https://www.googleapis.com/oauth2/v4/token",
      "sub": "<your service account's email style identifier>",
      "iss": "<your service account's email style identifier>",
      "target_audience": "<the URL of the cloud function you're trying to call>",
      "exp": <unix epoch timestamp + 3600 as an integer>,
      "iat": <unix epoch timestamp as an integer>
    }
    
  2. Base64 编码声明。根据 doc #3 中的通用说明,Base64 编码声明 header 集 ({"alg":"RS256","typ":"JWT"}) 并将结果与​​句点 header.claim 组合。你应该得到这样的东西:eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjkt...。与文档 #3 相反,您不需要 header 中的 kid

  3. 使用服务帐户私钥与您喜欢的 JWT 库签署 JWT

  4. 通过 POST 使用 [=19] 调用 https://www.googleapis.com/oauth2/v4/token,将您的服务帐户签名的 JWT 交换为来自 Google 的 OAuth 系统的访问令牌=] 和以下两个字段形成编码的数据:

    • grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
    • assertion: <signed JWT base64 encoded string, YES you use it twice>
  5. 如果一切顺利,您应该会收到包含密钥 id_token 的 JSON 响应,您可以在调用 CloudFunction 时在 Authorization: Bearer <id_token> 中使用它