Est-il sûr d'exposer apiKey Firebase au public?

439

Le guide de l'application Web Firebase indique que je devrais mettre les données apiKeydans mon HTML pour initialiser 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>

Ce faisant, le apiKeyest exposé à chaque visiteur. Quel est le but de cette clé et est-elle vraiment destinée à être publique?

farmio
la source
1
Je pense que tant que vous configurez les règles de base de données Firebase Auth et Firebase, vous pouvez donner cette information publiquement.
abbaf33f
L'utilisateur Christophe Quintard avait ajouté un lien vers un article très utile avec des informations supplémentaires concernant la sécurité des API Firebase, donc je le redistribue ici: javebratt.com/hide-firebase-api (Le commentaire va disparaître car il est attaché à un autre utilisateur réponse qui est signalée pour suppression en raison d'une mauvaise qualité)
Oliver Schafeld
Je veux juste souligner que ce n'est pas parce que ce cadre particulier est bien d'exposer son API que cela signifie que d'autres cadres sont OK avec lui. Je ne voudrais pas que quiconque s'éloigne de ce message avec l'idée que "c'est correct d'exposer les clés API" en général.
YungGun
vous exposez les clés sans problème. Pour le rendre sûr, vous pouvez le restreindre à un domaine spécifique en production afin que personne d'autre ne puisse appeler l'appel d'API à partir d'un nom de domaine aléatoire. Pour le rendre plus sûr, supprimez localhost de l'application de production.
BL Λ CK
1
Je ne pense pas que la suppression de localhost de la liste blanche de vos référents va faire quoi que ce soit, sauf rendre les tests plus difficiles. Cette configuration n'est pas comme une liste blanche IP; pensez plutôt à une configuration CORS. La façon dont Firebase fonctionne est que ces routes API sont appelées directement à partir des clients, elles ne sont pas mandatées. C'est pourquoi votre page Web a besoin de la clé API. Si un mauvais acteur veut appeler vos routes API à partir de Postman, votre liste blanche de référents ne les arrêtera pas. Il n'est utile que pour empêcher d'autres sites publics de se moquer de vos serveurs.
forresthopkinsa

Réponses:

452

L'apiKey de cet extrait de configuration identifie simplement votre projet Firebase sur les serveurs Google. Ce n'est pas un risque pour la sécurité que quelqu'un le sache. En fait, il est nécessaire qu'ils le sachent pour qu'ils puissent interagir avec votre projet Firebase. Ces mêmes données de configuration sont également incluses dans chaque application iOS et Android qui utilise Firebase comme backend.

En ce sens , il est très similaire à l'URL de base de données qui identifie la base de données back-end associée à votre projet dans le même extrait: https://<app-id>.firebaseio.com. Consultez cette question pour savoir pourquoi ce n'est pas un risque pour la sécurité: comment limiter la modification des données Firebase? , y compris l'utilisation des règles de sécurité côté serveur de Firebase pour garantir que seuls les utilisateurs autorisés peuvent accéder aux services backend.

Si vous souhaitez savoir comment sécuriser tous les accès aux données à vos services d'arrière-plan Firebase est autorisé, lisez la documentation sur les règles de sécurité Firebase .


Si vous souhaitez réduire le risque de soumettre ces données de configuration au contrôle de version, envisagez d'utiliser la configuration automatique du SDK de Firebase Hosting . Bien que les clés se retrouvent toujours dans le navigateur au même format, elles ne seront plus codées en dur dans votre code avec cela.

Frank van Puffelen
la source
7
Cela signifie donc que d'autres personnes pourraient accéder à toutes les données de ma base de données Firebase?
Emmanuel Campos
31
@EmmanuelCampos La réponse est Oui et Non. Oui, si vous autorisez ou souhaitez que les autres personnes accèdent à toutes les données de la base de données. Et non, si vous ne le souhaitez pas. La base de données Firebase a des règles, des règles que vous contrôlez
KhoPhi
5
J'ai trouvé ma réponse ici pour ma dernière question support.google.com/firebase/answer/6400741 Merci pour l'aide. Ce lien peut aider quelqu'un à l'avenir.
Emmanuel Campos
7
@ m.rufca, vos données doivent être disponibles pour les utilisateurs authentifiés. Et voici l'astuce. Par défaut, dans vos paramètres Firebase, seul l'hôte local et les domaines de votre projet sont autorisés à effectuer une authentification à partir d'eux. Donc, personne d'autre ne peut créer une application qui fonctionnera normalement avec votre base de feu.
Artem Arkhipov
15
Et si le bot crée un nombre illimité d'utilisateurs sur mon application. Comment puis-je exiger du captcha.
Muhammad Umer
79

Sur la base des réponses de prufrofro et Frank van Puffelen ici , j'ai mis en place cette configuration qui n'empêche pas le grattage, mais peut rendre légèrement plus difficile l'utilisation de votre clé API.

Attention: Pour obtenir vos données, même avec cette méthode, on peut par exemple simplement ouvrir la console JS dans Chrome et taper:

firebase.database().ref("/get/all/the/data").once("value", function (data) {
    console.log(data.val());
});

Seules les règles de sécurité de la base de données peuvent protéger vos données.

Néanmoins, j'ai limité l'utilisation de ma clé d'API de production à mon nom de domaine comme ceci:

  1. https://console.developers.google.com/apis
  2. Sélectionnez votre projet Firebase
  3. Identifiants
  4. Sous Clés API, choisissez votre clé de navigateur. Il devrait ressembler à ceci: " Clé de navigateur (créée automatiquement par le service Google) "
  5. Dans « Accepter les demandes de ces référants HTTP (sites web) », ajoutez l'URL de votre application (exemple: projectname.firebaseapp.com/*)

Maintenant, l'application ne fonctionnera que sur ce nom de domaine spécifique. J'ai donc créé une autre clé API qui sera privée pour le développement localhost.

  1. Cliquez sur Créer des informations d'identification> Clé API

Par défaut, comme mentionné par Emmanuel Campos, Firebase seulement whitelists localhostet votre domaine d' hébergement Firebase .


Afin de ne pas publier par erreur la mauvaise clé API, j'utilise l'une des méthodes suivantes pour utiliser automatiquement la plus restreinte en production.

Configuration de Create-React-App

Dans /env.development:

REACT_APP_API_KEY=###dev-key###

Dans /env.production:

REACT_APP_API_KEY=###public-key###

Dans /src/index.js

const firebaseConfig = {
  apiKey: process.env.REACT_APP_API_KEY,
  // ... 
};

Ma configuration précédente pour Webpack:

J'utilise Webpack pour créer mon application de production et je mets ma clé API de développement dans mon index.htmlcomme vous le feriez normalement. Ensuite, à l'intérieur de mon webpack.production.config.jsfichier, je remplace la clé chaque fois qu'elle index.htmlest copiée dans la build de production:

plugins: [
    new CopyWebpackPlugin([
      {
        transform: function(content, path) {
          return content.toString().replace("###dev-key###", "###public-key###");
        },
        from: './index.html'
      }
    ])
  ]
maintenant
la source
1
Cela fonctionne-t-il bien pour vous? Pensais à faire la même chose pour une application Android. Je me demande pourquoi Firebase ne couvre pas cela dans la section sécurité.
steliosf
2
Je n'ai eu aucun problème jusqu'à présent, mais probablement pas d'attaques non plus
maintenant
3
Cela n'est pas mentionné dans leur guide car cela ne vous protégera pas du grattage. Tout cela garantit que quelqu'un d'autre ne peut pas créer une application Web qui utilise votre base de feu pour lire (ou écrire) des données, si elle est exécutée dans un navigateur normal bien comporté.
thoutbeckers
@thoutbeckers vous avez raison, merci. J'ai édité la réponse, mais j'ai laissé la méthode car elle pourrait encore être utile.
maintenant
1
@FrankvanPuffelen D'après ce que je comprends, cela ne fait pas une grande différence, mais il peut être un peu plus ennuyeux d'abuser de votre quota, car dans un navigateur bien comporté, la clé API servie avec HTML / JS ne fonctionnera que sur le prévu domaine (s) et non localhost ou autre chose. Mais je conviens que la protection supplémentaire est marginale par rapport à ce que Firebase fournit déjà. Je reformulerai la réponse à quelque chose de moins dramatique.
maintenant le
22

Je ne suis pas convaincu d'exposer les clés de sécurité / configuration au client. Je ne dirais pas que c'est sécurisé, pas parce que quelqu'un peut voler toutes les informations privées du premier jour, parce que quelqu'un peut faire une demande excessive, drainer votre quota et vous faire payer beaucoup d'argent à Google.

Vous devez penser à de nombreux concepts, de restreindre les gens à ne pas accéder là où ils ne sont pas censés être, aux attaques DOS, etc.

Je préférerais davantage que le client frappe d'abord sur votre serveur Web, là vous mettez ce pare-feu de première main, captcha, cloudflare, sécurité personnalisée entre le client et le serveur, ou entre le serveur et la base de feu et vous êtes prêt à partir. Au moins, vous pouvez d'abord arrêter l'activité suspecte avant qu'elle n'atteigne la base de feu. Vous aurez beaucoup plus de flexibilité.

Je ne vois qu'un seul bon scénario d'utilisation pour utiliser la configuration basée sur le client pour les usages internes. Par exemple, vous avez un domaine interne et vous êtes sûr que les étrangers ne peuvent pas y accéder, vous pouvez donc configurer un environnement comme le navigateur -> type de base de feu.

Teoman shipahi
la source
10
Mais n'est-ce pas la même chose que «d'exposer» une autre API REST? Je veux dire avec l'URL de l'API REST sont disponibles pour l'utilisateur. Ils peuvent utiliser l'URL pour faire toutes les demandes qu'ils souhaitent et drainer votre quota. Ce que Firebase fait, c'est d'utiliser config avec des clés api pour identifier votre partie de backend et c'est et elle doit être disponible pour que l'utilisateur puisse faire des requêtes.
mbochynski
3
@mbochynski, mais vous pouvez faire des demandes directes aux ressources qui vous font payer la facture. Et du côté de Firebase, il n'y a pas beaucoup de mécanisme de contrôle pour empêcher les attaques DDoS, etc. s'il s'agit de demandes légitimes. (via Cloudflare, etc.). ou récupérer les résultats du cache. Ensuite, vous n'atteindrez vos ressources Firebase que si vous en avez besoin. C'est ce que j'implémenterais firebase.google.com/docs/admin/setup
Teoman shipahi
3
exposer les clés au navigateur est sérieusement une mauvaise idée. à ceux qui ont écrit tous ces guides / articles, à quoi pensaient-ils? référent http pour la sécurité? qui est facilement usurpé
Nick Chan Abdullah
1
Vous ne pensez pas à ce droit. Ne considérez pas la clé API comme un secret; ce n'est pas une clé privée, c'est juste un ID, donc l'API Firebase sait qui accède à quel projet. Si vous voulez beaucoup de flexibilité et que vous devez contrôler chaque étape de l'interaction serveur / client, vous ne devez pas utiliser Firebase, vous devez utiliser GCP.
forresthopkinsa
@forresthopkinsa J'ai le lien ci-dessus commente l'approche à adopter. Personne ici n'est assez naïf pour suggérer que c'est une clé secrète.
Teoman shipahi
4

Je crois qu'une fois les règles de base de données rédigées avec précision, il suffira de protéger vos données. De plus, il existe des directives que l'on peut suivre pour structurer votre base de données en conséquence. Par exemple, créer un nœud UID sous les utilisateurs et placer tous les informations sous lui. Après cela, vous devrez implémenter une règle de base de données simple comme ci-dessous

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

Aucun autre utilisateur ne pourra lire les données des autres utilisateurs, de plus, la politique de domaine restreindra les demandes provenant d'autres domaines. On peut en savoir plus à ce sujet sur les règles de sécurité Firebase

Bhupiister singh
la source
3

L'exposition de clé API crée une vulnérabilité lorsque l'inscription de l'utilisateur / mot de passe est activée. Il existe un point de terminaison API ouvert qui prend la clé API et permet à quiconque de créer un nouveau compte d'utilisateur. Ils peuvent ensuite utiliser ce nouveau compte pour se connecter à votre application protégée par Firebase Auth ou utiliser le SDK pour authentifier avec l'utilisateur / passer et exécuter des requêtes.

J'ai signalé cela à Google, mais ils disent que cela fonctionne comme prévu.

Si vous ne pouvez pas désactiver les comptes d'utilisateur / mot de passe, vous devez procéder comme suit: Créez une fonction cloud pour désactiver automatiquement les nouveaux utilisateurs surCreate et créez une nouvelle entrée de base de données pour gérer leur accès.

Ex: MyUsers / {userId} / Access: 0

exports.addUser = functions.auth.user().onCreate(onAddUser);
exports.deleteUser = functions.auth.user().onDelete(onDeleteUser);

Mettez à jour vos règles pour autoriser uniquement les lectures pour les utilisateurs avec un accès> 1.

Au cas où la fonction d'écoute ne désactiverait pas le compte assez rapidement, les règles de lecture les empêcheraient de lire les données.

bzk
la source
3

Après avoir lu ceci et après avoir fait quelques recherches sur les possibilités, j'ai trouvé une approche légèrement différente pour restreindre l'utilisation des données par des utilisateurs non autorisés:

J'enregistre également mes utilisateurs dans ma base de données (et j'y enregistre les données de profil). Je viens donc de définir les règles de base de données comme ceci:

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

De cette façon, seul un utilisateur enregistré antérieur peut ajouter de nouveaux utilisateurs dans la base de données, il est donc impossible pour quiconque sans compte d'effectuer des opérations sur la base de données. l'ajout de nouveaux utilisateurs n'est possible que si l'utilisateur a un rôle spécial et ne modifie que par l'administrateur ou par cet utilisateur lui-même (quelque chose comme ça):

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

Vous ne devez pas exposer ces informations. en public, spécialement les touches api. Cela peut entraîner une fuite de confidentialité.

Avant de rendre le site Web public, vous devez le cacher. Vous pouvez le faire de 2 manières ou plus

  1. Codage / masquage complexe
  2. Il suffit de mettre les codes SDK Firebase au bas de votre site Web ou de votre application pour que Firebase fasse automatiquement tous les travaux. vous n'avez pas besoin de mettre de clés API n'importe où
user12449933
la source
1
Je cite un extrait de Firebase, "Copiez et collez ces scripts au bas de votre balise <body>, mais avant d'utiliser des services Firebase", qui comprend la clé API
Luke-zhang-04