我现在一直在努力奋斗几个小时,如果不是几天,似乎无法修复它。
我的云功能请求被拒绝,错误代码为: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域,而且我正在使用本地主机。
首先感谢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) {
}