¿Es seguro exponer Firebase apiKey al público?

439

La guía de la aplicación web Firebase dice que debo poner lo dado apiKeyen 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, apiKeyse expone a cada visitante. ¿Cuál es el propósito de esa clave y si realmente debe ser pública?

farmio
fuente
1
Creo que siempre que configure las reglas de Firebase Auth y Firebase database puede dar esa información públicamente.
abbaf33f
El usuario Christophe Quintard había agregado un enlace a un artículo muy útil con información adicional sobre la seguridad de las API de Firebase, así que lo estoy volviendo a publicar aquí: javebratt.com/hide-firebase-api (El comentario va a desaparecer porque está adjunto a otro usuario respuesta que está marcada para su eliminación debido a la mala calidad)
Oliver Schafeld
Solo quiero señalar que solo porque este marco en particular está bien con exponer su API, eso no significa que otros marcos estén bien con él. No quisiera que nadie se aleje de esta publicación con la idea de que "está bien exponer API Keys" en general.
YungGun
Expones las llaves sin ningún problema. Para que sea seguro, puede restringirlo con un dominio específico en producción para que nadie más pueda realizar llamadas de API desde cualquier nombre de dominio aleatorio. Para hacerlo más seguro, elimine localhost de la aplicación de producción.
BL Λ CK
1
No creo que eliminar localhost de la lista blanca de sus referencias vaya a hacer nada, excepto hacer que las pruebas sean más difíciles. Esa configuración no es como una lista blanca de IP; piense más como una configuración CORS. La forma en que Firebase funciona es que esas rutas API se llaman directamente desde los clientes, no son proxy. Es por eso que su página web necesita la clave API. Si un mal actor quiere llamar a sus rutas API desde Postman, su lista blanca de referencia no las detendrá. Solo es útil para evitar que otros sitios públicos se salgan de sus servidores.
forresthopkinsa

Respuestas:

452

La apiKey en este fragmento de configuración solo 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. Estos mismos datos de configuración también se incluyen en todas las aplicaciones de iOS y Android que usan Firebase como back-end.

En ese sentido, es muy similar a la URL base de datos que identifica la base de datos back-end asociado con su proyecto en el mismo fragmento: 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 aprender a proteger todos los datos de acceso a sus servicios back-end de Firebase, lea la documentación sobre las reglas de seguridad de Firebase .


Si desea reducir el riesgo de comprometer estos datos de configuración al control de versiones, considere usar la configuración automática de SDK de Firebase Hosting . Si bien las claves terminarán en el navegador en el mismo formato, ya no estarán codificadas en su código con eso.

Frank van Puffelen
fuente
77
¿Entonces significa que otras personas podrían acceder a todos los datos en mi base de datos de Firebase?
Emmanuel Campos
31
@EmmanuelCampos La respuesta es Sí y No. Sí, si permite o desea que otras personas accedan a todos los datos de la base de datos. Y no, si no quieres que lo hagan. La base de datos de Firebase tiene reglas, reglas que controlas
KhoPhi
55
Encontré mi respuesta aquí para mi última pregunta support.google.com/firebase/answer/6400741 Gracias por la ayuda. Este enlace puede ayudar a alguien en el futuro.
Emmanuel Campos
77
@ m.rufca, sus datos deben estar disponibles para usuarios autenticados. Y aquí está el truco. De manera predeterminada, en la configuración de Firebase solo localhost y los dominios de su proyecto están autorizados para realizar la autenticación desde ellos. Por lo tanto, nadie más puede crear una aplicación que normalmente funcione con su base de fuego.
Artem Arkhipov
15
¿Qué pasa si el bot está creando usuarios ilimitados en mi aplicación? ¿Cómo puedo requerir captcha?
Muhammad Umer
79

Sobre la base de las respuestas de prufrofro y Frank van Puffelen aquí , armé esta configuración que no evita el raspado, pero puede hacer que sea un poco más difícil usar 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:

  1. https://console.developers.google.com/apis
  2. Selecciona tu proyecto de Firebase
  3. Cartas credenciales
  4. 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) "
  5. En " Aceptar las peticiones de estos referentes HTTP (sitios web) ", añadir la URL de su aplicación (Ejemplo: projectname.firebaseapp.com/*)

Ahora la aplicación solo funcionará en este nombre de dominio específico. Así que creé otra clave API que será privada para el desarrollo localhost.

  1. Haga clic en Crear credenciales> Clave API

Por defecto, como lo menciona Emmanuel Campos, Firebase solo incluye las listas blancas localhosty su dominio de alojamiento de Firebase .


Para asegurarme de que no publico la clave API incorrecta por error, utilizo uno de los siguientes métodos para utilizar automáticamente la clave más restringida en producción.

Configuración para crear-reaccionar-aplicación

En /env.development:

REACT_APP_API_KEY=###dev-key###

En /env.production:

REACT_APP_API_KEY=###public-key###

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.htmltal como lo haría normalmente. Luego, dentro de mi webpack.production.config.jsarchivo, reemplazo la clave cada vez que index.htmlse copia 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'
      }
    ])
  ]
ahora
fuente
1
¿Funciona bien para ti? Estaba pensando en hacer lo mismo para una aplicación de Android. Me pregunto por qué Firebase no cubre eso en la sección de seguridad.
steliosf
2
Hasta ahora no he tenido ningún problema, pero probablemente tampoco haya ataques
ahora
3
Esto no se menciona en su guía porque no lo protegerá del raspado. Todo esto garantiza que alguien más no pueda hacer una aplicación web que use su base de fuego para leer (o escribir) datos, si se ejecuta en un navegador normal con buen comportamiento.
thoutbeckers
@thoutbeckers tienes razón, gracias. Edité la respuesta, pero dejé el método ya que aún podría ser útil.
ahora
1
@FrankvanPuffelen Por lo que entiendo, no hace una gran diferencia, pero puede hacer que sea un poco más molesto abusar de su cuota, ya que en un navegador con buen comportamiento, la clave API servida con HTML / JS solo funcionará en la intención dominio (s) y no localhost o cualquier otra cosa. Pero estoy de acuerdo en que la protección adicional es marginal en comparación con lo que Firebase ya proporciona. Reformularé la respuesta a algo menos dramático.
ahora
22

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 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.

Teoman shipahi
fuente
10
Pero, ¿no es lo mismo que "exponer" cualquier otra API REST? Es decir, con REST API URL están disponibles para el usuario. Pueden usar la URL para realizar cualquier solicitud que deseen y agotar su cuota. Lo que Firebase hace es usar la configuración con las claves de la API para identificar su parte del backend y lo es y tiene que estar disponible para que el usuario realice solicitudes.
mbochynski
3
@mbochynski, pero de alguna manera puede hacer solicitudes directas a los recursos que causan que pague la factura. Y en el lado de Firebase no hay mucho mecanismo de control para prevenir ataques DDoS, etc. Mi sugerencia sería que tu cliente llame a tu API REST, pero esa API REST debe tener las claves API de forma privada, e incluso antes de que golpees los recursos de Firebase, valídalos si son solicitudes legítimas (a través de Cloudflare, etc.). o recuperar resultados del caché. Entonces solo golpeará sus recursos de Firebase solo si lo necesita. Esto es lo que implementaría firebase.google.com/docs/admin/setup
Teoman shipahi
3
exponer las claves en el navegador es una mala idea. aquellos que escribieron todas estas guías / artículos, ¿qué estaban pensando? referencia http para la seguridad? eso es fácil de falsificar
Nick Chan Abdullah
1
Ustedes no están pensando en esto bien. No piense en la clave API como un secreto; no es una clave privada, es solo una identificación para que la API de Firebase sepa quién está accediendo a qué proyecto. Si desea mucha flexibilidad y necesita controlar cada paso de la interacción servidor / cliente, entonces no debería usar Firebase, debería usar GCP.
forresthopkinsa
@forresthopkinsa Tengo el enlace de arriba comentar qué enfoque tomar. Nadie aquí lo suficientemente ingenuo como para sugerir que es una clave secreta.
Teoman shipahi
4

Creo que una vez que las reglas de la base de datos se escriban con precisión, será suficiente para proteger sus datos. Además, hay pautas que uno puede seguir para estructurar su base de datos en consecuencia. Por ejemplo, hacer un nodo UID debajo de los usuarios y poner todo debajo de la información debajo de él. Después de eso, deberá implementar una regla de base de datos simple como se muestra a continuación

  "rules": {
    "users": {
      "$uid": {
        ".read": "auth != null && auth.uid == $uid",
        ".write": "auth != null && auth.uid == $uid"
      }
    }
  }
}

Ningún otro usuario podrá leer los datos de otros usuarios, además, la política de dominio restringirá las solicitudes procedentes de otros dominios. Uno puede leer más sobre esto en las reglas de seguridad de Firebase

Bhupiister singh
fuente
3

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 como se esperaba

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.

bzk
fuente
3

Después de leer esto y después de investigar un poco sobre las posibilidades, se me ocurrió un enfoque ligeramente diferente para restringir el uso de datos por parte de usuarios no autorizados:

También guardo a mis usuarios en mi base de datos (y guardo los datos del perfil allí). Así que acabo de establecer las reglas de db de esta manera:

".read": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()",
".write": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()"

De esta manera, solo un usuario guardado anteriormente puede agregar nuevos usuarios a la base de datos, por lo que no hay forma de que nadie sin una cuenta pueda realizar operaciones en la base de datos. También es posible agregar nuevos usuarios solo si el usuario tiene un rol especial y solo lo edita el administrador o el propio usuario (algo como esto):

"userdata": {
  "$userId": {
    ".write": "$userId === auth.uid || root.child('/userdata/'+auth.uid+'/userRole').val() === 'superadmin'",
   ...
Berci
fuente
-2

No debes exponer esta información. en público, especialmente teclas api. Puede conducir a una fuga de privacidad.

Antes de hacer público el sitio web, debe ocultarlo. Puedes hacerlo de 2 o más formas

  1. Codificación / ocultación compleja
  2. Simplemente coloque los códigos SDK de firebase en la parte inferior de su sitio web o aplicación para que firebase realice automáticamente todo el trabajo. no necesitas poner claves API en ningún lado
usuario12449933
fuente
1
Cito de Firebase, "Copie y pegue estos scripts en la parte inferior de su etiqueta <body>, pero antes de usar cualquier servicio de Firebase", que incluye la clave API
Luke-zhang-04