firebase javascript example
¿Es seguro exponer Firebase apiKey al público? (4)
La apiKey esencialmente identifica su proyecto Firebase en los servidores de Google. No es un riesgo de seguridad que alguien lo sepa. De hecho, es necesario que lo sepan para poder interactuar con su proyecto Firebase.
En ese sentido, es muy similar a la URL de la base de datos que Firebase ha usado históricamente para identificar el back-end:
https://<app-id>.firebaseio.com
.
Vea esta pregunta sobre por qué esto no es un riesgo de seguridad:
¿Cómo restringir la modificación de datos de Firebase?
, incluido el uso de las reglas de seguridad del lado del servidor de Firebase para garantizar que solo los usuarios autorizados puedan acceder a los servicios de fondo.
Si desea obtener información sobre cómo proteger todos los datos de acceso a sus servicios back-end de Firebase, lea la documentación sobre las reglas de seguridad de Firebase .
La guía de la aplicación web firebase indica que debo poner la clave api dada en mi HTML para inicializar 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>
Al hacerlo, la apiKey queda expuesta a todos los visitantes. ¿Cuál es el propósito de esa clave y si realmente está destinada a ser pública?
La exposición a la clave API crea una vulnerabilidad cuando el registro de usuario / contraseña está habilitado. Hay un punto final API abierto que toma la clave API y permite a cualquiera crear una nueva cuenta de usuario. Luego pueden usar esta nueva cuenta para iniciar sesión en su aplicación protegida Firebase Auth o usar el SDK para autenticar con el usuario / pasar y ejecutar consultas.
He informado de esto a Google pero dicen que está funcionando según lo previsto.
Si no puede deshabilitar las cuentas de usuario / contraseña, debe hacer lo siguiente: Crear una función en la nube para deshabilitar automáticamente a los nuevos usuarios en Crear y crear una nueva entrada de base de datos para administrar su acceso.
Ej: MyUsers / {userId} / Access: 0
exports.addUser = functions.auth.user().onCreate(onAddUser); exports.deleteUser = functions.auth.user().onDelete(onDeleteUser);
Actualice sus reglas para permitir solo lecturas para usuarios con acceso> 1.
Si la función de escucha no desactiva la cuenta lo suficientemente rápido, las reglas de lectura evitarán que lean cualquier dato.
No estoy convencido de exponer las claves de seguridad / configuración al cliente. No lo llamaría seguro, no porque alguien pueda robar toda la información privada desde el primer día, porque alguien puede hacer una solicitud excesiva y agotar su cuota y hacer que le deba mucho dinero a Google.
Debe pensar en muchos conceptos: restringir a las personas para que no accedan a donde se supone que no deben estar, ataques DOS, etc.
Prefiero que el cliente llegue primero a su servidor web, allí puede poner el firewall de primera mano, captcha, cloudflare, seguridad personalizada entre el cliente y el servidor, o entre el servidor y firebase y ya está listo. Al menos puedes detener la actividad sospechosa antes de que llegue a la base de fuego. Tendrás mucha más flexibilidad.
Solo veo un buen escenario de uso para usar la configuración basada en el cliente para usos internos. Por ejemplo, tiene un dominio interno y está bastante seguro de que los extraños no pueden acceder allí, por lo que puede configurar el entorno como navegador -> tipo de base de fuego.
Sobre la base de las respuestas de prufrofro y Frank van Puffelen aquí , armé esta solución que no evita el raspado, pero puede dificultar el uso de su clave API.
Advertencia: para obtener sus datos, incluso con este método, uno puede, por ejemplo, simplemente abrir la consola JS en Chrome y escribir:
firebase.database().ref("/get/all/the/data").once("value", function (data) {
console.log(data.val());
});
Solo las reglas de seguridad de la base de datos pueden proteger sus datos.
Sin embargo, restringí el uso de mi clave de API de producción a mi nombre de dominio de esta manera:
- https://console.developers.google.com/apis
- Selecciona tu proyecto de Firebase
- Cartas credenciales
- En Claves de API, elija la clave de su navegador. Debería verse así: " Clave del navegador (creada automáticamente por el Servicio de Google) "
-
En "
Aceptar solicitudes de estos referentes HTTP (sitios web)
", agregue la URL de su aplicación (ejemplo:
projectname.firebaseapp.com/*
)
Ahora la aplicación solo funcionará en este nombre de dominio. Así que creé otra clave API que será privada para el desarrollo localhost.
- Haga clic en Crear credenciales> Clave API
Este no está restringido, así que asegúrese de mantenerlo en privado.
Por defecto, como mencionó Emmanuel Campos, support.google.com/firebase/answer/6400741 .
Para asegurarme de que no publico esta nueva clave API sin restricciones por error, utilizo uno de los siguientes métodos para utilizar automáticamente la restringida en producción.
Configuración para crear-reaccionar-aplicación
En
/env.development
:
plugins: [
new CopyWebpackPlugin([
{
transform: function(content, path) {
return content.toString().replace("###dev-key###", "###public-key###");
},
from: ''./index.html''
}
])
]
En
/env.production
:
exports.addUser = functions.auth.user().onCreate(onAddUser);
exports.deleteUser = functions.auth.user().onDelete(onDeleteUser);
En
/src/index.js
const firebaseConfig = { apiKey: process.env.REACT_APP_API_KEY, // ... };
Mi configuración anterior para Webpack:
Utilizo Webpack para construir mi aplicación de producción y pongo mi clave de API de desarrollo dentro de mi
index.html
como lo haría normalmente.
Luego, dentro de mi archivo
webpack.production.config.js
, reemplazo la clave cada vez que se copia
index.html
en la compilación de producción:
plugins: [ new CopyWebpackPlugin([ { transform: function(content, path) { return content.toString().replace("###dev-key###", "###public-key###"); }, from: ''./index.html'' } ]) ]