Google apps script 通过谷歌应用程序脚本安全地调用谷歌云功能

Google apps script 通过谷歌应用程序脚本安全地调用谷歌云功能,google-apps-script,oauth,oauth-2.0,google-cloud-functions,google-oauth,Google Apps Script,Oauth,Oauth 2.0,Google Cloud Functions,Google Oauth,如何通过谷歌应用程序脚本安全地调用谷歌云功能 ✅ 我有一个谷歌云功能,我可以在https://MY_REGION-MY_PROJECT.cloudfunctions.net/MY_FUNCTION,我希望允许某些用户通过应用程序脚本调用它 ✅ 为了保护云函数的安全,我将云函数调用程序设置为只包含已知的电子邮件(例如USER@COMPANY.com,其中这是一封有效的谷歌电子邮件) ✅ 我能够通过curl成功地调用云函数,同时使用此电子邮件登录到gcloud,方法是运行:curlhttps://M

如何通过谷歌应用程序脚本安全地调用谷歌云功能

✅ 我有一个谷歌云功能,我可以在
https://MY_REGION-MY_PROJECT.cloudfunctions.net/MY_FUNCTION
,我希望允许某些用户通过应用程序脚本调用它

✅ 为了保护云函数的安全,我将云函数调用程序设置为只包含已知的电子邮件(例如
USER@COMPANY.com
,其中这是一封有效的谷歌电子邮件)

✅ 我能够通过curl成功地调用云函数,同时使用此电子邮件登录到gcloud,方法是运行:
curlhttps://MY_REGION-MY_PROJECT.cloudfunctions.net/MY_FUNCTION -H“授权:持票人$(gcloud auth print identity token)”

✅ 我已在我的应用程序脚本的清单中授予以下OAuthScope:

  • ”https://www.googleapis.com/auth/script.external_request“
  • ”https://www.googleapis.com/auth/userinfo.email“
  • ”https://www.googleapis.com/auth/cloud-platform“
⛔️ 但是,当我尝试通过Google Apps脚本调用云功能时,我使用电子邮件
USER@COMPANY.com
,我无法调用它,而是返回了一个401。以下是我尝试调用云函数的方式:

const token = ScriptApp.getIdentityToken();
const options = {
  headers: {'Authorization': 'Bearer ' + token}
}
UrlFetchApp.fetch("https://MY_REGION-MY_PROJECT.cloudfunctions.net/MY_FUNCTION", options);
ℹ️ 我还尝试了以下方法:

  • 使用
    ScriptApp.getOAuthToken()
  • 添加其他OAuthScope,例如
    openid
  • 使用
    https://script.google.com
    设置为授权的Javascript源代码
  • 部署应用程序脚本
  • 绝望地向天空呼喊

    • 感谢您的评论,您可以做两件事。但在此之前,您必须知道,您不能(或者至少我从来没有做到这一点),创建一个有效的身份令牌,以便通过云功能进行身份验证,并使用用户凭据运行云

      但您可以使用用户凭据调用Google Cloud API!所以

      • 你可以用。配额限制您每100分钟拨打16次电话(当然,这是为测试而设计的!)
      • 您可以将邮件发布到和中。在这种模式中,您的调用是异步的

      我很难通过应用程序脚本进行身份验证来调用一个云运行的应用程序,而且我认为调用任何包含云功能的谷歌云应用程序都是一样的。本质上,目标是调用一个HTTP方法,该方法通过使用您已经作为用户运行了Apps脚本的身份验证信息进行保护

      我认为缺少的一步是,只有当应用程序脚本和谷歌云功能(或我的例子中的运行容器)在同一个GCP项目中时,您使用的技术才会起作用。(请参见如何。)

      以这种方式进行设置要简单得多:当您将脚本与GCP项目关联时,这会自动为项目创建一个配置,而应用程序脚本的
      getIdentityToken
      函数将返回一个仅对该客户端ID有效的身份令牌(它被编码到令牌字段中)。如果您想要为另一个项目工作的身份令牌,您需要以另一种方式获得

      如果您能够将脚本和GCP功能或应用程序放在同一个GCP项目中,您还必须执行以下操作,其中许多操作您已经执行过:

      • 通过
        curl成功测试云功能的身份验证https://MY_REGION-MY_PROJECT.cloudfunctions.net/MY_FUNCTION -H“授权:持票人$(gcloud auth print identity token)”
        (按说明)。如果这失败了,那么您会遇到与堆栈溢出问题不同的问题,所以我省略了这方面的故障排除步骤

      • 确保你确实是。您无法从电子表格中的自定义函数获取标识令牌,因为它们是匿名运行的。在其他情况下,应用程序脚本代码可能作为其他人运行,例如某些触发器

      • 如前所述重新部署云功能(或类似地,如前所述重新部署云运行容器),以便应用程序将拾取任何新的客户端ID配置。这是在创建任何新的客户端ID后需要的,包括通过向GCP项目添加或重新添加脚本自动创建的客户端ID。(如果将脚本移动到另一个GCP项目,然后再将其移回,则似乎会创建另一个客户端ID,而不是重用旧的客户端ID,旧的客户端ID将停止工作。)

      • 添加(以及所有其他需要的作用域,例如
        https://www.googleapis.com/auth/script.external_request
        )在中明确显示
        getIdentityToken()
        将返回
        null
        ,而不包含可能导致此错误的
        openid
        范围。读者注意:仔细阅读此要点-作用域名称字面上只是“
        openid
        ”-它不像其他作用域那样是URL

        "oauthScopes": ["openid", "https://...", ...]
        
      • 使用和不使用
        getOAuthToken()
        。根据我读到的内容,getOAuthToken()返回一个访问令牌,而不是标识令牌。访问令牌不能证明您的身份;相反,它们只是授予访问某些资源的权限

      如果无法将脚本添加到与GCP应用程序相同的项目中,我不知道该怎么办,因为我从未成功尝试过。通常,您的任务是获取一个绑定到GCP客户端ID之一的OAuth标识令牌。我不认为一个应用程序(或GCP项目)应该能够为不同的OAuth应用程序(不同的GCP项目)获取身份令牌。无论如何,这还是有可能的。Google在他们的网站中讨论了OAuth认证的高级别。如果由于应用程序脚本不允许浏览器重定向,而让用户单击重定向链接,则使用a执行常规操作可能对用户当前操作有效。如果你只是需要
      async function callCloudFunction() {
        const token = ScriptApp.getIdentityToken();
        const options = {
          headers: {'Authorization': 'Bearer ' + token}
        }
        const data = JSON.parse(await UrlFetchApp.fetch("https://MY_REGION-MY_PROJECT.cloudfunctions.net/MY_FUNCTION", options).getContentText())
        return data
      }