Google Cloud Storage node/credential: write requests sent with no Authorization header (works for reads, fails for writes)

这个报错通常发生在 n8n 使用 Google Service Account 凭据( googleApi )向 Google Cloud Storage 执行“写”操作时,请求没有携带 Authorization 头,被 Google 当成匿名调用者拒绝;读操作正常、凭据测试也通过,所以排查重点应

快速结论:这个报错通常发生在 n8n 使用 Google Service Account 凭据(googleApi)向 Google Cloud Storage 执行“写”操作时,请求没有携带 Authorization 头,被 Google 当成匿名调用者拒绝;读操作正常、凭据测试也通过,所以排查重点应放在请求执行路径是否真的附加了认证,而不是先怀疑 IAM 权限。

适用环境:Issue 中确认的工具为 n8n;确认的节点为 Google Cloud Storage 节点(resource object,operation create / get)以及 Generic HTTP Request 节点(authentication: predefinedCredentialType,nodeCredentialType: googleApi)。Issue 未提供操作系统、Python、CUDA、显卡或依赖版本信息。

最快修复方案:暂无确认的一步修复方案。Issue 讨论中验证的方向是:在请求辅助边界增加认证解析追踪(auth_strategy_selected、token_resolution_attempted、authorization_header_attached 等),先把“凭据测试通过”与“实际请求附加了认证”区分开,再定位写路径为何没有走认证边界。

注意事项:Issue 已确认 GCP 侧 IAM 绑定正确(Policy Troubleshooter 评估为 “Can access”),服务账号具备 Storage Object Admin,因此继续按权限问题排查可能走偏。读操作与写操作行为不一致,说明问题更可能在 n8n 的凭据注入/请求认证层,而不是 GCS 节点 create 实现或目标桶权限。Issue 讨论中提出的追踪字段与回归矩阵属于建议方案,尚未在 Issue 中标注为已验证修复。

问题场景

用户在 n8n 中使用同一个 Google Service Account 凭据(googleApi)执行 Google Cloud Storage 写操作时触发问题。复现方式有两种:

  1. 使用 Google Cloud Storage 节点,resource 设为 object,operation 设为 create(上传或覆盖对象),失败并报匿名调用。
  2. 使用 Generic HTTP Request 节点,设置 authentication: predefinedCredentialType、nodeCredentialType: googleApi,直接 POST 到 GCS JSON API 上传端点,同样失败并出现相同症状。

同一凭据、同一工作流、同一执行中,读操作(resource object,operation get,alt: media,下载对象)可以成功。凭据在 n8n 凭据 UI 中的 “Test connection” 检查也能通过。用户已通过 GCP 的 Policy Troubleshooter 确认服务账号在目标桶上具有 storage.objects.create 所需 IAM 绑定,评估结果为 “Can access”。失败请求约 100ms 完成,不足以完成 JWT 签名加 OAuth token 交换,提示该代码路径可能根本没有进行令牌交换。

报错原文

NodeApiError: Authorization failed - please check your credentials
httpCode: 401

{
  "error": {
    "code": 401,
    "message": "Anonymous caller does not have storage.objects.create access to the Google Cloud Storage object. Permission 'storage.objects.create' denied on resource '//storage.googleapis.com/projects/_/buckets/petitgenius-user-content/objects/diagnostic-test.txt' (or it may not exist). Remediate access with this Troubleshooter URL or share it with your administrator - https://console.cloud.google.com/iam-admin/troubleshooter/summary;errorId=...",
    "errors": [
      {
        "message": "Anonymous caller does not have storage.objects.create access ...",
        "domain": "global",
        "reason": "required",
        "locationType": "header",
        "location": "Authorization"
      }
    ]
  }
}

Google 返回的 "reason": "required"、"locationType": "header"、"location": "Authorization" 明确表示请求缺少 Authorization 头,而不是仅权限不足。

原因分析

最可能的原因在 n8n 的凭据注入层:写操作路径没有为请求附加 Authorization 头,或者根本没有选择任何认证策略。证据包括:

  • 同一凭据读操作成功,写操作失败,说明并非凭据本身无效或 GCP IAM 配置错误。
  • Generic HTTP Request 节点使用 predefined googleApi 凭据 POST 到 GCS 上传端点时同样失败,说明问题不是 Google Cloud Storage 节点 create 实现独有,而是该凭据类型在通用 HTTP 请求路径中也有相同问题。
  • 失败请求约 100ms 完成,不足以完成 JWT 签名与 OAuth token 交换,提示令牌交换可能根本没有发生。
  • 凭据 UI 的 “Test connection” 通过,说明凭据材料本身有效,但不能证明具体执行路径会附加认证。

Issue 讨论认为,当前凭据测试会误导操作者,因为绿色的测试结果只证明“某条 Google 认证路径可以获取/使用凭据”,不证明“请求操作对应的执行路径会附加这些凭据”。可优先尝试在请求辅助边界增加认证解析追踪,以区分“令牌交换失败”和“执行路径根本没有选择认证策略”。

环境排查

  • 确认 n8n 版本与是否已有针对该问题的修复;Issue 元数据未提供具体版本号,需以实际运行版本为准。
  • 确认凭据类型为 Google Service Account(googleApi),且凭据 UI 中 “Test connection” 的状态。
  • 确认触发问题的节点类型:Google Cloud Storage 节点的 object.create,或 Generic HTTP Request 节点使用 predefinedCredentialType + googleApi。
  • 确认同一工作流中 object.get 读操作是否仍然成功,用于判断问题是否只出现在写路径。
  • 在 GCP 侧确认服务账号对目标桶的 IAM 绑定(Issue 中已确认 Storage Object Admin 且 Policy Troubleshooter 显示 “Can access”)。
  • 检查执行数据中 Google 返回的响应体,确认是否包含 "location": "Authorization" 与 "reason": "required"。
  • Issue 未提供操作系统、Python、CUDA、PyTorch、显卡型号或相关依赖版本,因此无需将这些项作为本问题的前置排查条件。

解决步骤

  1. 先复现读/写差异:用同一个 Google Service Account 凭据,在同一工作流内分别执行 object.get(读)和 object.create(写),确认失败是否只出现在写路径。
  2. 用 Generic HTTP Request 节点做交叉验证:authentication 设为 predefinedCredentialType,nodeCredentialType 设为 googleApi,POST 到 GCS JSON API 上传端点。如果同样报匿名调用,说明问题在凭据注入层,可排除 GCS 节点 create 自身实现。
  3. 在 GCP 侧使用 Policy Troubleshooter 检查 storage.objects.create 权限,确认服务账号在目标桶上的 IAM 绑定与评估结果。Issue 中该步骤结果为 “Can access”,因此不应继续把 IAM 作为主要修复方向。
  4. 检查失败请求的实际响应体,确认 Google 返回的 location 是否为 Authorization、reason 是否为 required,以区分“缺少认证头”与“权限不足”。
  5. 可优先尝试在请求辅助(request-helper)边界增加脱敏的认证解析追踪,记录类似以下字段:credential_type = googleApi、operation = object.create、auth_strategy_selected = service_account_jwt | oauth2 | none、token_resolution_attempted = true/false、authorization_header_attached = true/false。这可以直接判断是令牌交换失败,还是执行路径完全没有选择认证策略。
  6. 如果是要提交修复或补充测试,可优先尝试建立回归矩阵:用一个 service account 凭据分别验证 object GET、object CREATE/upload、Generic HTTP GET 使用 predefined googleApi、Generic HTTP POST 使用 predefined googleApi,并检查请求是否附加了认证,而不仅仅检查模拟端点是否返回 2xx。
  7. 在 UI 或日志层面,可优先尝试把状态拆分为 “Credential material valid: yes” 和 “Requested operation auth path verified: yes/no”,避免 “Test connection” 成功继续把操作者引向 IAM 排查。

验证方法

修复或调整后,用同一个 Google Service Account 凭据分别执行以下操作并检查请求头或追踪字段:object.get、object.create、Generic HTTP Request 使用 predefined googleApi 的 GET 和 POST。确认写操作请求已附加 Authorization 头、auth_strategy_selected 不为 none、authorization_header_attached 为 true,且不再出现 Anonymous caller does not have storage.objects.create access。同时确认凭据 UI 的 “Test connection” 状态与实际操作认证路径状态能够区分开。

参考来源

n8n-io/n8n #35143

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 25534

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注