使用 PHP 和身份验证的 Firebase REST 访问
Firebase REST access using PHP with Authentication
我正在尝试使用 PHP 从服务器访问 Firebase,Firebase 的 REST 的 Google Auth library, and a wrapper...这非常适合实现此目的:
use Firebase\JWT\JWT;
use Google\Auth\Credentials\ServiceAccountCredentials;
use Google\Auth\HttpHandler\HttpHandlerFactory;
use GuzzleHttp\Client;
$email = 'account@email.com';
$key = 'private_key_goes_here';
$scopes = [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/firebase.database',
];
$creds = [
'client_email' => $email,
'private_key' => $key,
];
$serviceAccount = new ServiceAccountCredentials($scopes, $creds);
$handler = HttpHandlerFactory::build(new Client());
$token = $serviceAccount->fetchAuthToken($handler);
$firebase = new \Firebase\FirebaseLib($url, $token);
$value = $firebase->get('test/hello');
# $value now stores "world"
但是,这要求Firebase中的安全规则是通用读/写的,这是我不希望的。如果我将我的安全规则更新为:
{
"rules": {
"test": {
".read": "auth != null"
}
}
}
$value
中的结果变为 {"error": "Permission denied"}
。我进行了广泛的搜索,并尝试了许多排列组合和可能的解决方案,但没有得出结论性的结果。
我已经使用 this code 向终端客户提供 JWT 令牌,终端客户可以成功使用它们并毫无问题地利用安全规则。我最初对服务器尝试了相同的方法,但没有成功。我选择尝试结合这两种方法:
# Snipping code that didn't change...
$serviceAccount = new ServiceAccountCredentials($scopes, $creds);
$handler = HttpHandlerFactory::build(new Client());
$payload = [
'iss' => $email,
'sub' => $email,
'aud' => 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit',
'iat' => time(),
'exp' => time() + 60 * 60,
'uid' => '123',
'claims' => [
'uid' => '123',
],
];
$payload = $serviceAccount->updateMetadata($payload);
$token = JWT::encode($payload, $key, 'RS256');
$firebase = new \Firebase\FirebaseLib($url, $token);
$value = $firebase->get('test/hello');
这似乎很接近,但 $value
现在包含 {"error": "Missing claim 'kid' in auth header."}
。为了解决这个问题,我修改了编码调用:
$token = JWT::encode($payload, $key, 'RS256', 'key_id_goes_here');
这导致了一个略有不同的错误:Invalid claim 'kid' in auth header.
,表明我在正确的轨道上......但不完全正确。直接使用 JWT 令牌会产生完全相同的结果。任何想法我做错了什么?电子邮件、私钥和密钥 ID 都直接来自我创建服务帐户时提供的 json
凭据文件。
我查看了数十页的文档和帖子,以下是最有帮助的:
您可以在使用将成为安全规则中的 auth
变量的服务帐户进行身份验证时指定 auth_variable_override
查询参数。它应该是一个正确转义的 JSON 对象。例如要执行 {"uid":123}
你要添加:
?auth_variable_override=%7B%22uid%22%3A%22123%22%7D
至您的请求结束 URL。
最终,我最终使用的解决方案是切换 PHP 库。我最初拒绝了 this library,因为它正朝着 PHP7 的方向发展,我还没有准备好迁移到它,但当前版本 (1.1) 运行良好:
use Kreait\Firebase\Configuration;
use Kreait\Firebase\Firebase;
$clientId = '1234567890';
$email = 'account@email.com';
$key = 'private_key_goes_here';
$url = 'https://example.firebaseio.com';
$fbConfig = new Configuration();
$fbConfig->setAuthConfigFile([
'type' => 'service_account',
'client_id' => $clientId,
'client_email' => $email,
'private_key' => $key,
]);
$fb = new Firebase($url, $fbConfig);
$value = $fb->get('test/hello');
# $value now stores "world"
我正在尝试使用 PHP 从服务器访问 Firebase,Firebase 的 REST 的 Google Auth library, and a wrapper...这非常适合实现此目的:
use Firebase\JWT\JWT;
use Google\Auth\Credentials\ServiceAccountCredentials;
use Google\Auth\HttpHandler\HttpHandlerFactory;
use GuzzleHttp\Client;
$email = 'account@email.com';
$key = 'private_key_goes_here';
$scopes = [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/firebase.database',
];
$creds = [
'client_email' => $email,
'private_key' => $key,
];
$serviceAccount = new ServiceAccountCredentials($scopes, $creds);
$handler = HttpHandlerFactory::build(new Client());
$token = $serviceAccount->fetchAuthToken($handler);
$firebase = new \Firebase\FirebaseLib($url, $token);
$value = $firebase->get('test/hello');
# $value now stores "world"
但是,这要求Firebase中的安全规则是通用读/写的,这是我不希望的。如果我将我的安全规则更新为:
{
"rules": {
"test": {
".read": "auth != null"
}
}
}
$value
中的结果变为 {"error": "Permission denied"}
。我进行了广泛的搜索,并尝试了许多排列组合和可能的解决方案,但没有得出结论性的结果。
我已经使用 this code 向终端客户提供 JWT 令牌,终端客户可以成功使用它们并毫无问题地利用安全规则。我最初对服务器尝试了相同的方法,但没有成功。我选择尝试结合这两种方法:
# Snipping code that didn't change...
$serviceAccount = new ServiceAccountCredentials($scopes, $creds);
$handler = HttpHandlerFactory::build(new Client());
$payload = [
'iss' => $email,
'sub' => $email,
'aud' => 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit',
'iat' => time(),
'exp' => time() + 60 * 60,
'uid' => '123',
'claims' => [
'uid' => '123',
],
];
$payload = $serviceAccount->updateMetadata($payload);
$token = JWT::encode($payload, $key, 'RS256');
$firebase = new \Firebase\FirebaseLib($url, $token);
$value = $firebase->get('test/hello');
这似乎很接近,但 $value
现在包含 {"error": "Missing claim 'kid' in auth header."}
。为了解决这个问题,我修改了编码调用:
$token = JWT::encode($payload, $key, 'RS256', 'key_id_goes_here');
这导致了一个略有不同的错误:Invalid claim 'kid' in auth header.
,表明我在正确的轨道上......但不完全正确。直接使用 JWT 令牌会产生完全相同的结果。任何想法我做错了什么?电子邮件、私钥和密钥 ID 都直接来自我创建服务帐户时提供的 json
凭据文件。
我查看了数十页的文档和帖子,以下是最有帮助的:
您可以在使用将成为安全规则中的 auth
变量的服务帐户进行身份验证时指定 auth_variable_override
查询参数。它应该是一个正确转义的 JSON 对象。例如要执行 {"uid":123}
你要添加:
?auth_variable_override=%7B%22uid%22%3A%22123%22%7D
至您的请求结束 URL。
最终,我最终使用的解决方案是切换 PHP 库。我最初拒绝了 this library,因为它正朝着 PHP7 的方向发展,我还没有准备好迁移到它,但当前版本 (1.1) 运行良好:
use Kreait\Firebase\Configuration;
use Kreait\Firebase\Firebase;
$clientId = '1234567890';
$email = 'account@email.com';
$key = 'private_key_goes_here';
$url = 'https://example.firebaseio.com';
$fbConfig = new Configuration();
$fbConfig->setAuthConfigFile([
'type' => 'service_account',
'client_id' => $clientId,
'client_email' => $email,
'private_key' => $key,
]);
$fb = new Firebase($url, $fbConfig);
$value = $fb->get('test/hello');
# $value now stores "world"