Javascript 云计算运行+;云端点+;服务帐户身份验证&x2013;在curl中工作,但不';在JS中使用fetchapi时

Javascript 云计算运行+;云端点+;服务帐户身份验证&x2013;在curl中工作,但不';在JS中使用fetchapi时,javascript,google-cloud-functions,google-cloud-endpoints,bearer-token,google-cloud-run,Javascript,Google Cloud Functions,Google Cloud Endpoints,Bearer Token,Google Cloud Run,我已经配置了一个执行GCF的云端点。当云运行服务允许allUsers调用API时,一切正常 一旦我删除alluser并使用服务帐户进行身份验证,就会在云运行控制台中显示403个错误: 请求未通过身份验证。允许未经验证的调用或设置正确的授权标头。阅读更多 Chrome JS控制台显示以下错误消息: 在'https://.run.app/do-this&key="从源头上说, 'http://0.0.0.0:8080'已被CORS策略阻止:对飞行前请求的响应不可用 通过访问控制检查:请求的服务器上不

我已经配置了一个执行GCF的云端点。当云运行服务允许allUsers调用API时,一切正常

一旦我删除
alluser
并使用服务帐户进行身份验证,就会在云运行控制台中显示403个错误:

请求未通过身份验证。允许未经验证的调用或设置正确的授权标头。阅读更多

Chrome JS控制台显示以下错误消息:

在'https://.run.app/do-this&key="从源头上说, 'http://0.0.0.0:8080'已被CORS策略阻止:对飞行前请求的响应不可用 通过访问控制检查:请求的服务器上不存在“访问控制允许来源”标题 资源。如果不透明响应满足您的需要,请将请求的模式设置为“no cors”以获取 已禁用CORS的资源

这是我在浏览器中运行的JS代码:

let选项:RequestInit={
标题:{
'Authorization':'Bearer${token}`,
},
}
const result=wait fetch(fetchURL,选项);
当使用相同的令牌运行curl时,我得到了预期的响应

curl-H“授权:承载${token}”https://.run.app/do-this&key='
为了完整起见,这里还有端点yaml

swagger:'2.0'
信息:
标题:我的第一个小部件
描述:这是一个很棒的小部件
版本:1.0.0
主机:.run.app
计划:
-https
生产:
-应用程序/json
路径:
/这样做:
获取:
小结:这样做吗
操作ID:doit
x-google-backend:
地址:https://.cloudfunctions.net/do-that
响应:
'200':
描述:成功响应。
模式:
类型:字符串
'403':
描述:发生错误
模式:
类型:字符串
安全:
-api_键:[]
证券定义:
#本节使用API密钥配置基本身份验证。
api_密钥:
类型:“apiKey”
名称:“钥匙”
在“查询”中
更新esp的命令:

gcloud运行服务更新--set env vars=“^ | ^ENDPOINTS_SERVICE_NAME=.run.app | ESP_ARGS=--rollout_strategy=managed,--cors_preset=basic”--project=--platform=managed--region=europe west1
更新 启用cors浏览器端没有帮助

谷歌文档提到应该可以

如果您正在从无法访问计算元数据的计算实例(例如,您自己的服务器)调用服务,则必须手动生成适当的令牌:
将目标受众声明设置为接收服务的URL,对服务帐户JWT进行自签名。 将自签名JWT交换为谷歌签名的ID令牌,该令牌应将aud声明设置为上述URL。 在服务请求的Authorization:Bearer ID_token头中包含ID令牌。 尽管身份识别代理还不支持云运行(完全管理),但您可以检查身份识别代理示例代码,以获取上述步骤的代码示例

:不过提到了CORS

构建web应用程序时,必须考虑跨源资源共享(CORS)问题。例如,CORS飞行前请求在没有授权标头的情况下发送,因此它们在非公共服务上被拒绝。由于飞行前请求失败,主请求也将失败。
为了解决这个问题,您可以在同一个域上托管web应用程序和服务,以避免CORS飞行前请求。您可以通过使用Firebase托管来实现这一点

我尝试在Firebase主机上托管JS脚本和HTML,但问题仍然存在

我想到的另一个问题是:在开放式API规范中,是否需要将OAuth与API密钥身份验证一起设置

更新2
表明不可能使用云运行并支持CORS的身份验证。我还在想为什么卷曲的时候会有这种可能。我正在使用服务帐户令牌进行身份验证,而不是最终用户。

云端点的COR未激活。像这样更新openAPI规范

swagger: '2.0'
info:
  title: My first widget
  description: This is a great widget
  version: 1.0.0
host: <my-api>.run.app
x-google-endpoints:
- name: <my-api>.run.app
  allowCors: True
...
...
...
swagger:'2.0'
信息:
标题:我的第一个小部件
描述:这是一个很棒的小部件
版本:1.0.0
主机:.run.app
x-google-endpoints:
-名称:.run.app
allowCors:正确
...
...
...

或者按照错误消息所述设置
无cors
签入您的呼叫。

我已通过以下方式使其工作:

  • oauth
    作为安全定义添加到OpenAPI规范中,并在每个api路径的api密钥中使用它
  • 使用
    --set env vars=“^ | ^ENDPOINTS_SERVICE_NAME=.run.app | ESP_ARGS=--cors_preset=basic,--rollout_strategy=managed”
  • 在云函数中,将
    访问控制允许原点设置为空字符串
    '
    res.setHeader(“访问控制允许原点)”,'')
  • 允许allUsers访问云运行容器
  • 虽然每个人都可以访问云运行容器,但端点负责身份验证

    让我吃惊的是,CF自动将调用主机(例如,
    mydomain.com
    )和
    *
    添加到
    访问控制允许源站
    标题中。此标题中不允许有多个项目,因此我将删除
    mydomain.com
    并保留
    *

    我将尝试使用不同的选项,一旦完成,我将提供所有相关步骤的操作指南。非常感谢您的任何意见/建议

    更新 在深入挖掘之后,我现在了解到,
    accesscontrolalloworigin
    是由
    constcors=require('cors')({Origin:true})自动添加的

    对于我的用例,我不需要t中的cors