401 Unauthorized 尝试调用谷歌云功能时

Posted

技术标签:

【中文标题】401 Unauthorized 尝试调用谷歌云功能时【英文标题】:401 Unauthorized When trying to call a google cloud functions 【发布时间】:2021-10-06 06:20:08 【问题描述】:

我在 Google Cloud Function 中有一个简单的 node.js 函数(从我的网站代码内部调用),我之前使用了我在 Google Cloud SDK 中连接并使用它时获得的 id_token:gcloud auth print-identity-token ,但它只持续了 60 分钟,所以在那之后我的应用程序就不能再使用谷歌云功能了。

所以我尝试在服务帐户密钥的帮助下生成自己的令牌:https://cloud.google.com/docs/authentication/production#create_service_account

但是当我使用“授权:承载令牌”标头调用我的链接时,我总是得到一个“401 未授权”

可能是因为我不知道在“aud”值(在有效负载数组内)中放入什么

<?php

namespace MyProject\Parser;

use Firebase\JWT\JWT;
use GuzzleHttp\Client;

abstract class GoogleCloudParser extends AbstractParser

    /**
     * Returns the html for the given URL
     * @param string $url
     * @return string
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    protected function getHTML(string $url): string
    
        $cloudFunctionURL = "https://region-project-name.cloudfunctions.net/function-name";
        $token = $this->getToken();


        $guzzle = new Client();
        $response = $guzzle->get($cloudFunctionURL, [
            'query' => ['url' => $url],
            'headers' => [
                'Authorization' => "Bearer " . $token
            ]
        ]);

        return $response->getBody()->getContents();
    

    /**
     * Returns the authentification token for google cloud
     * @return string
     */
    protected function getToken()
    
        $privateKey = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n";
        $publicKey = "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n";    

        $payload = [
            'iss' => 'App-Engine-default-service-account@appspot.gserviceaccount.com',
            'sub' => 'App-Engine-default-service-account@appspot.gserviceaccount.com',
            'aud' => 'bucket-name',
            'iat' => time(),
            'exp' => (time() + 3600)
        ];

        $header = [
            "alg" => "RS256",
            "typ" => "JWT",
            "kid" => "private_key_id_of_app_engine_default_service-account"
        ];


        $token = JWT::encode($payload, $privateKey, $header["alg"], $header["kid"]);

        return $token;
    

我尝试了多种方法来添加“aud”,但我不知道该使用什么...我尝试使用我得到的存储桶名称:https://github.com/GoogleCloudPlatform/php-docs-samples/blob/78356e87cc54c1d46df52c0d2f47320329957ce5/auth/src/auth_api_explicit.php

使用 cmd 行:php src/auth_api_explicit.php myGoogleProjectID gcloud-service-account-file.json

我尝试使用“https://cloudfunctions.googleapis.com/”...

我尝试将我的函数名称的完整链接放在谷歌云函数中。

我认为我已经在 IAM 和 Google Cloud 平台内为我的服务帐户设置了所有内容。

请问有什么帮助吗?

【问题讨论】:

【参考方案1】:

看着你的代码我有点困惑,因为useFirebase\JWT\JWT;,但你用于自定义令牌的服务帐户说App-Engine-default-service-account,并且在aud 中你有一个存储桶名称。找了一会儿发现,为了避免401错误,你需要确保服务账户在管理控制台的Domain-wide delegation页面中为子声明(字段)中的用户授权。

关于您可以在aud 中输入的内容,您可以尝试输入https://firebase.googleapis.com/,但我又不能完全确定这一点,因为我对您的代码有点困惑。

最好的问候。

【讨论】:

我不知道域范围的委托在哪里...我试图找到它但到目前为止没有运气... 我认为现在最好的方法是进行授权的 API 调用,您需要执行 3 个步骤,即创建 SWT,从 google OAuth 2.0 授权服务器请求访问令牌,最后您需要处理您得到的回复,因为您的问题是在aud 中放入什么,您可以放入https://oauth2.googleapis.com/token,但为了避免任何进一步的麻烦,您可以查看this 文档,该文档解释了我刚刚告诉的内容你 您好,所以我找到了一个解决方案,并在aud 中使用了https://www.googleapis.com/oauth2/v4/token,然后使用响应id_token 将其用作承载令牌授权,并且成功了。感谢您的帮助!

以上是关于401 Unauthorized 尝试调用谷歌云功能时的主要内容,如果未能解决你的问题,请参考以下文章

当我尝试通过 keycloak 调用我的安全 API 时收到状态 401 Unauthorized

与 jquery 对 webmethod 的调用一致地获得“401 Unauthorized”错误

每次响应 401 Unauthorized 时在 DEV Env 中调用休息,PROD 工作正常

ASP.Net 页面调用报告服务 Web 服务得到“401 Unauthorized”错误

401 Unauthorized - 当尝试点击 Spring 应用程序的休息服务时

护照-jwt 401 未经授权