Я пытаюсь получить доступ к Firebase с сервера, используя PHP, Библиотека Google Auth, и обертка для REST Firebase … Это прекрасно работает, чтобы сделать это:
use Firebase\JWT\JWT;
use Google\Auth\Credentials\ServiceAccountCredentials;
use Google\Auth\HttpHandler\HttpHandlerFactory;
use GuzzleHttp\Client;
$email = '[email protected]';
$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"}
, Я много искал и пробовал многочисленные перестановки и возможные решения без каких-либо окончательных результатов.
Я использовал этот код предоставлять токены 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 напрямую дает те же самые результаты. Есть идеи, что я делаю не так? Электронная почта, закрытый ключ и идентификатор ключа пришли прямо из json
Файл учетных данных предоставляется при создании учетной записи службы.
Я просмотрел десятки страниц документации и постов, вот те, которые были самыми полезными:
Крест размещен на Firebase Google Group.
Вы можете указать auth_variable_override
параметр запроса при аутентификации с помощью учетной записи службы, которая станет auth
переменная в правилах безопасности. Это должен быть правильно экранированный объект JSON. Например сделать {"uid":123}
Вы хотели бы добавить:
?auth_variable_override=%7B%22uid%22%3A%22123%22%7D
в конце вашего запроса URL.
В конечном итоге, решение, которое я выбрал, заключалось в переключении библиотек PHP. Я изначально уволил эта библиотека потому что он движется к поддержке только PHP7, к которой я еще не готов перейти, но текущая версия (1.1) работала нормально:
use Kreait\Firebase\Configuration;
use Kreait\Firebase\Firebase;
$clientId = '1234567890';
$email = '[email protected]';
$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"