Google PHP Api客户端 - 我一直收到错误401:UNAUTHENTICATED

问题描述 投票:1回答:2

我现在一直在努力奋斗几个小时,如果不是几天,似乎无法修复它。

我的云功能请求被拒绝,错误代码为:401:UNAUTHENTICATED。

我的守则如下:

    putenv('GOOGLE_APPLICATION_CREDENTIALS=' . FIREBASE_SERIVCE_PATH);

    $client = new Google_Client();
    $client->useApplicationDefaultCredentials();
    $client->addScope(Google_Service_CloudFunctions::CLOUD_PLATFORM);
    $httpClient = $client->authorize();


    $promise = $httpClient->requestAsync("POST", "<MyCloudFunctionExecutionUri>", ['json' => ['data' => []]]);
    $promise->then(
        function (ResponseInterface $res) {
            echo "<pre>";
            print_r($res->getStatusCode());
            echo "</pre>";

        },
        function (RequestException $e) {
            echo $e->getMessage() . "\n";
            echo $e->getRequest()->getMethod();
        }
    );
    $promise->wait();

我目前正在从localhost执行此操作,因为我还处于开发阶段。

我的FIREBASE_SERIVCE_PATH常量链接到我的service_account js

我的云功能index.js:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();


// CORS Express middleware to enable CORS Requests.
const cors = require('cors')({
  origin: true,
});

exports.testFunction = functions.https.onCall((data, context) => {
    return new Promise((resolve, reject) => {
        resolve("Ok:)");
    });
  });
  // [END all]

我的云功能日志:Function execution took 459 ms, finished with status code: 401

我做错了什么,所以我得到了未经认证的?

PS:我的testFunction在我的Flutter移动应用程序中调用时效果很好:使用:https://pub.dartlang.org/packages/cloud_functions

更新:

我已经遵循了本指南:https://developers.google.com/api-client-library/php/auth/service-accounts,但在“委派服务帐户的域范围权限”部分中,它仅说明如果我的应用程序在Google Apps域中运行,但我不会使用Google Apps域,而且我正在使用本地主机。

php google-api google-cloud-functions google-api-php-client
2个回答
1
投票

可调用函数在常规HTTP函数之上强加了protocol。通常,您使用Firebase客户端SDK调用它们。由于您没有可以使用的SDK来实现协议,因此您必须自己关注它。您不能像普通的HTTP函数一样调用它们。

如果您不想实现protocol,则应使用常规HTTP功能,并停止在移动应用程序中使用客户端SDK。


1
投票

首先感谢Doug Stevenson的上述答案!它帮助我为可调用函数(functions.https.onCall)获得了一个可行的解决方案。主要思想是此类功能需要已登录的Firebase用户的身份验证上下文。它不是服务帐户,而是Firebase项目的“身份验证”部分中的用户记录。因此,首先,我们必须授权用户,从响应中获取ID令牌,然后使用此令牌来请求调用可调用函数。所以,下面是我的工作片段(实际上来自Drupal 8项目)。

use Exception;
use Google_Client;
use Google_Service_CloudFunctions;
use GuzzleHttp\Psr7;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Promise;
use GuzzleHttp\RequestOptions;

$client = new Google_Client();
$config_path = <PATH TO SERVICE ACCOUNT JSON FILE>;
$json = file_get_contents($config_path);
$config = json_decode($json, TRUE);
$project_id = $config['project_id'];
$options = [RequestOptions::SYNCHRONOUS => TRUE];
$client->setAuthConfig($config_path);
$client->addScope(Google_Service_CloudFunctions::CLOUD_PLATFORM);
$httpClient = $client->authorize();
$handler = $httpClient->getConfig('handler');

/** @var \Psr\Http\Message\ResponseInterface $res */
$res = $httpClient->request('POST', "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=<YOUR FIREBASE PROJECT API KEY>", [
  'json' => [
    'email' => <FIREBASE USER EMAIL>,
    'password' => <FIREBASE USER PASSWORD>,
    'returnSecureToken' => TRUE,
  ],
]);
$json = $res->getBody()->getContents();
$data = json_decode($json);
$id_token = $data->idToken;

$request = new Request('POST', "https://us-central1-$project_id.cloudfunctions.net/<YOUR CLOUD FUNCTION NAME>", [
  'Content-Type' => 'application/json',
  'Authorization' => "Bearer $id_token",
], Psr7\stream_for(json_encode([
  'data' => [],
])));

try {
  $promise = Promise\promise_for($handler($request, $options));
}
catch (Exception $e) {
  $promise = Promise\rejection_for($e);
}

try {
  /** @var \Psr\Http\Message\ResponseInterface $res */
  $res = $promise->wait();
  $json = $res->getBody()->getContents();
  $data = json_decode($json);
  ...
}
catch (Exception $e) {
}
© www.soinside.com 2019 - 2024. All rights reserved.