Безопасно ли выставлять apiKey Firebase широкой публике?
Руководство Firebase Web-App гласит, что я должен поместить указанный apiKey в мой HTML, чтобы инициализировать firebase:
// TODO: Replace with your project's customized code snippet
<script src="https://www.gstatic.com/firebasejs/3.0.2/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: '<your-api-key>',
authDomain: '<your-auth-domain>',
databaseURL: '<your-database-url>',
storageBucket: '<your-storage-bucket>'
};
firebase.initializeApp(config);
</script>
При этом apiKey открыт для каждого посетителя. Какова цель этого ключа и действительно ли он должен быть публичным?
12 ответов
По сути, apiKey просто идентифицирует ваш проект Firebase на серверах Google. Это не угроза безопасности для кого-то, кто это знает. На самом деле, им необходимо это знать, чтобы они могли взаимодействовать с вашим проектом Firebase.
В этом смысле он очень похож на URL базы данных, которую Firebase исторически использовал для идентификации серверной части: https://<app-id>.firebaseio.com
, Посмотрите на этот вопрос, почему это не представляет угрозы для безопасности: как ограничить изменение данных Firebase? включая использование правил безопасности Firebase на стороне сервера, чтобы гарантировать, что только авторизованные пользователи могут получить доступ к внутренним службам.
Опираясь на ответы пруфрофро и Фрэнка ван Пуффелена, я собрал это решение, которое не предотвращает очистку, но может затруднить использование вашего ключа API.
Предупреждение. Чтобы получить данные, даже с помощью этого метода, можно, например, просто открыть консоль JS в Chrome и ввести:
firebase.database().ref("/get/all/the/data").once("value", function (data) {
console.log(data.val());
});
Только правила безопасности базы данных могут защитить ваши данные.
Тем не менее, я ограничил использование моего производственного API-ключа своим доменным именем следующим образом:
- https://console.developers.google.com/apis
- Выберите свой проект Firebase
- полномочия
- В разделе "Ключи API" выберите ключ браузера. Это должно выглядеть так: "Ключ браузера (автоматически создается сервисом Google)"
- В разделе " Принимать запросы от этих HTTP-рефереров (веб-сайтов)" добавьте URL своего приложения (например:
projectname.firebaseapp.com/*
)
Теперь приложение будет работать только на этом доменном имени. Поэтому я создал еще один API-ключ, который будет закрыт для разработки на локальном хосте.
- Нажмите Создать учетные данные> Ключ API
Этот не ограничен, поэтому убедитесь, что вы держите его в секрете.
Я использую Webpack для создания своего производственного приложения. Чтобы я по ошибке не опубликовал этот новый неограниченный ключ API, я поместил его в свойindex.html
так же, как вы обычно делаете с вашим ключом API. Тогда внутри моегоwebpack.production.config.js
файл, я заменяю ключ каждый раз index.html
копируется в производственную сборку, например так:
plugins: [
new CopyWebpackPlugin([
{
transform: function(content, path) {
return content.toString().replace("###dev-key###", "###public-key###");
},
from: './index.html'
}
])
]
По умолчанию, как упоминал Эммануэль Кампос, Firebase только белые спискиlocalhost
и ваш хостинг домен Firebase.
Я не убежден, чтобы выставить ключи безопасности / конфигурации клиенту. Я бы не назвал это безопасным, не потому что кто-то может украсть всю личную информацию с первого дня, потому что кто-то может сделать чрезмерный запрос, истощить вашу квоту и заставить вас задолжать Google много денег.
Вам нужно подумать о многих концепциях: от ограничения доступа людей к месту, где они не должны быть, до DOS-атак и т. Д.
Я бы предпочел, чтобы клиент сначала попадал на ваш веб-сервер, там вы устанавливаете межсетевой экран, капчу, облачный флаг, настраиваемую безопасность между клиентом и сервером или между сервером и базой данных, и вы готовы к работе. По крайней мере, вы можете сначала остановить подозрительную активность, прежде чем она достигнет базы огня. У вас будет гораздо больше гибкости.
Я вижу только один хороший сценарий использования клиентского конфига для внутреннего использования. Например, у вас есть внутренний домен, и вы почти уверены, что посторонние не могут получить к нему доступ, поэтому вы можете настроить среду, такую как browser -> firebase type.
ПРЕДОСТАВЛЕНИЕ КЛЮЧЕЙ API НЕ ЯВЛЯЕТСЯ РИСКОМ ДЛЯ БЕЗОПАСНОСТИ, НО ЛЮБОЙ МОЖЕТ РАЗМЕСТИТЬ ВАШИ УЧЕТНЫЕ ДАННЫЕ НА СВОЕМ САЙТЕ.
Открытые ключи api приводят к атакам, которые могут использовать много ресурсов в firebase, что определенно будет стоить вам денег.
Вы всегда можете ограничить свои ключи проекта firebase доменами / IP.
https://console.cloud.google.com/apis/credentials/key
выберите идентификатор проекта и ключ и ограничьте его своим Android / iOs / веб-приложением.
Использование ключа API создает уязвимость при включении регистрации пользователя / пароля. Существует открытая конечная точка API, которая принимает ключ API и позволяет любому пользователю создавать новую учетную запись пользователя. Затем они могут использовать эту новую учетную запись для входа в приложение, защищенное аутентификацией Firebase, или использовать SDK для авторизации с запросами user/pass и run.
Я сообщил об этом в Google, но они говорят, что он работает как задумано.
Если вы не можете отключить учетные записи пользователей и паролей, вы должны сделать следующее: Создать облачную функцию для автоматического отключения новых пользователей onCreate и создать новую запись в БД для управления их доступом.
Пример: MyUsers/{userId}/ Доступ: 0
exports.addUser = functions.auth.user().onCreate(onAddUser);
exports.deleteUser = functions.auth.user().onDelete(onDeleteUser);
Обновите свои правила, чтобы разрешить чтение только пользователям с доступом> 1.
При случайном отключении функция слушателя не отключает учетную запись достаточно быстро, тогда правила чтения не позволят им прочитать какие-либо данные.
Я считаю, что как только правила базы данных будут написаны точно, этого будет достаточно для защиты ваших данных. Более того, есть рекомендации, которым можно следовать, чтобы структурировать вашу базу данных соответствующим образом. Например, создание узла UID для пользователей и размещение всей информации под ним. После этого вам нужно будет реализовать простое правило базы данных, как показано ниже.
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
}
Ни один другой пользователь не сможет читать данные других пользователей, более того, политика домена будет ограничивать запросы, поступающие из других доменов. Подробнее об этом можно прочитать в правилах Firebase Security.
Прочитав это и изучив возможности, я придумал несколько иной подход к ограничению использования данных неавторизованными пользователями:
Я тоже сохраняю своих пользователей в своей БД (и сохраняю там данные профиля). Поэтому я просто установил такие правила базы данных:
".read": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()",
".write": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()"
Таким образом, только предыдущий сохраненный пользователь может добавлять новых пользователей в БД, поэтому никто без учетной записи не сможет выполнять операции с БД. также добавление новых пользователей возможно только в том случае, если у пользователя есть особая роль, и редактировать его может только администратор или сам этот пользователь (что-то вроде этого):
"userdata": {
"$userId": {
".write": "$userId === auth.uid || root.child('/userdata/'+auth.uid+'/userRole').val() === 'superadmin'",
...
Их можно включать, и особая осторожность требуется только для Firebase ML или при использовании аутентификации Firebase.
Ключи API для Firebase отличаются от типичных ключей API: в отличие от того, как обычно используются ключи API, ключи API для служб Firebase не используются для управления доступом к внутренним ресурсам; это можно сделать только с помощью правил безопасности Firebase. Обычно вам нужно тщательно охранять ключи API (например, используя службу хранилища или задавая ключи как переменные среды); однако ключи API для служб Firebase можно включать в код или зарегистрированные файлы конфигурации.
Хотя ключи API для сервисов Firebase безопасно включать в код, есть несколько конкретных случаев, когда вы должны установить ограничения для вашего ключа API; например, если вы используете Firebase ML или аутентификацию Firebase с методом входа по электронной почте / паролю. Узнайте больше об этих случаях позже на этой странице.
Для получения дополнительной информации проверьте официальную документацию
Столкнулся с аналогичной проблемой только с рабочим процессом аутентификации. Если вы создаете учетные записи пользователей в Firebase из своего внешнего интерфейса, я бы попросил вас пересмотреть это. Если у вас нет серверного кода, который запускается в качестве предварительного триггера для создания пользователя Firebase, который проверяет, заходит ли пользователь из вашего приложения или нет, вам следует переключиться на создание пользователя из вашего серверного интерфейса и отключить всю регистрацию/ методы входа в консоль администратора. Поскольку ключи учетной записи внутренней службы отличаются от ключей внешней службы, они не будут отображаться, и вы можете управлять ими через предпочитаемый вами диспетчер учетных данных (переменные env и т. д.). Это также очень полезно, если ваша основная база данных не Firestore (как это происходит со многими корпоративными приложениями, которые интенсивно используют SQL, но нуждаются в Firebase для некоторых функций реального времени), и вам не нужны явные учетные данные от пользователя. для прямого входа в Firebase. В своем бэкэнде вы можете создать собственный токен, используя
getAuth()
.createCustomToken(uid)
.then((customToken) => {
// Send token back to client
})
.catch((error) => {
console.log('Error creating custom token:', error);
});
Затем этот пользовательский токен можно передать клиенту, где клиент сможет войти в firstore с помощью webSDK.
firebase.auth().signInWithCustomToken(customToken)
.then((userCredential) => {
// Signed in
var user = userCredential.user;
// ...
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
Вам по-прежнему потребуются очень надежные и тщательные правила безопасности, чтобы доступ был мелкозернистым и для RBAC. Но для меня проблема заключалась в использовании ключей конфигурации webSDK от клиента, пользователь мог создать учетную запись или войти в мой проект Firebase. Но таким образом гарантируется, что пользователь не сможет создать учетную запись и войти в нее, не пройдя через свой собственный бэкэнд.
Я делаю сайт блога на страницах github. У меня возникла идея встраивать комментарии в конец каждой страницы блога. Я понимаю, как firebase получает и предоставляет данные.
Я много раз тестировал проект и даже консоль. Я совершенно не согласен с высказыванием, что влит уязвим. Поверьте, нет проблем с публичным отображением вашего ключа api, если вы выполнили шаги по обеспечению конфиденциальности, рекомендованные firebase. Перейдите на https://console.developers.google.com/apis и выполните повышение безопасности.
Вы не должны раскрывать эту информацию. публично, особенно ключи api. Это может привести к утечке конфиденциальной информации.
Перед тем, как сделать сайт общедоступным, вы должны его скрыть. Вы можете сделать это двумя или более способами
- Сложное кодирование / сокрытие
- Просто поместите коды SDK firebase внизу вашего веб-сайта или приложения, и firebase автоматически выполнит всю работу. вам не нужно никуда класть ключи API
Вы можете использовать удаленную конфигурацию Firebase, с помощью которой он будет защищен.