Czy bezpieczne jest udostępnianie apiKey Firebase publicznie?

437

W przewodniku Firebase Web-App stwierdza się, że powinienem umieścić dane apiKeyw moim pliku HTML, aby zainicjować 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>

Dzięki temu apiKeyjest narażony na każdego odwiedzającego. Jaki jest cel tego klucza i czy naprawdę ma być publiczny?

farmio
źródło
1
Myślę, że dopóki skonfigurujesz reguły Firebase Auth i Firebase , możesz podać te informacje publicznie.
abbaf33f
Użytkownik Christophe Quintard dodał link do bardzo przydatnego artykułu z dodatkowymi informacjami na temat bezpieczeństwa interfejsów API Firebase, więc zamieszczam go tutaj: javebratt.com/hide-firebase-api (Komentarz zniknie, ponieważ jest dołączony do innego użytkownika odpowiedź oznaczona do usunięcia z powodu złej jakości)
Oliver Schafeld
Chcę tylko zaznaczyć, że tylko dlatego, że ten konkretny framework jest w porządku z ujawnieniem jego API, nie oznacza to, że inne framewory są w porządku. Nie chciałbym, aby ktokolwiek odszedł od tego postu, myśląc, że ogólnie „Udostępnianie kluczy API jest ogólnie”.
YungGun,
wystawiasz klucze bez problemu. Aby go zabezpieczyć, możesz ograniczyć go do określonej domeny w produkcji, aby nikt inny nie mógł nawiązywać połączeń API z dowolnej losowej nazwy domeny. Aby było bezpieczniej, usuń localhost z aplikacji produkcyjnej.
BL Λ CK
1
Nie sądzę, że usunięcie localhost z białej listy polecających zrobi cokolwiek poza utrudnianiem testowania. Ta konfiguracja nie przypomina białej listy adresów IP; pomyśl o tym bardziej jak o konfiguracji CORS. Sposób działania Firebase polega na tym, że te trasy API są wywoływane bezpośrednio od klientów, nie są one proxy. Dlatego twoja strona potrzebuje klucza API. Jeśli zły aktor chce zadzwonić do twoich tras API od Postmana, biała lista polecających nie zatrzyma ich. Przydaje się to tylko w celu uniemożliwienia innym stronom publicznym wymykania się z serwerów.
forresthopkinsa

Odpowiedzi:

450

ApiKey w tym fragmencie konfiguracji po prostu identyfikuje projekt Firebase na serwerach Google. Ktoś, kto to wie, nie stanowi zagrożenia bezpieczeństwa. W rzeczywistości muszą to wiedzieć, aby mogli wchodzić w interakcje z twoim projektem Firebase. Te same dane konfiguracyjne są również zawarte w każdej aplikacji na iOS i Androida, która używa Firebase jako zaplecza.

W tym sensie jest bardzo podobny do adresu URL bazy danych, który identyfikuje back-end bazy danych związane z projektem w tym samym fragmencie: https://<app-id>.firebaseio.com. Zobacz pytanie, dlaczego nie stanowi to zagrożenia bezpieczeństwa: Jak ograniczyć modyfikację danych Firebase? , w tym stosowanie reguł bezpieczeństwa po stronie serwera Firebase, aby zapewnić dostęp do usług zaplecza tylko autoryzowanym użytkownikom.

Jeśli chcesz się dowiedzieć, jak zabezpieczyć dostęp do wszystkich danych do usług zaplecza Firebase, jest autoryzowany, przeczytaj dokumentację dotyczącą zasad bezpieczeństwa Firebase .


Jeśli chcesz zmniejszyć ryzyko przekazania danych konfiguracyjnych do kontroli wersji, rozważ użycie automatycznej konfiguracji SDK Firebase Hosting . Chociaż klucze nadal będą się wyświetlać w przeglądarce w tym samym formacie, nie będą już na stałe zakodowane w kodzie.

Frank van Puffelen
źródło
7
Oznacza to, że inni ludzie będą mogli uzyskać dostęp do wszystkich danych w mojej bazie danych firebase?
Emmanuel Campos,
31
@EmmanuelCampos Odpowiedź brzmi: tak i nie. Tak, jeśli pozwalasz lub chcesz, aby inne osoby miały dostęp do wszystkich danych w bazie danych. I nie, jeśli nie chcesz. Baza danych Firebase ma reguły, które kontrolujesz
KhoPhi
5
Znalazłem tutaj odpowiedź na moje ostatnie pytanie support.google.com/firebase/answer/6400741 Dziękujemy za pomoc. Ten link może pomóc komuś w przyszłości.
Emmanuel Campos,
7
@ m.rufca, twoje dane powinny być dostępne dla użytkowników, którzy są uwierzytelnieni. A oto sztuczka. Domyślnie w ustawieniach bazy ogniowej tylko localhost i domeny projektu są upoważnione do przeprowadzania z nich uwierzytelniania. Więc nikt inny nie może stworzyć aplikacji, która normalnie będzie działać z twoją bazą ogniową.
Artem Arkhipov
15
co jeśli bot tworzy w mojej aplikacji nieograniczoną liczbę użytkowników? Jak mogę wymagać captcha.
Muhammad Umer,
79

Opierając się na odpowiedziach prufrofro i Franka van Puffelena tutaj , stworzyłem tę konfigurację, która nie zapobiega skrobaniu, ale może nieco utrudnić korzystanie z klucza API.

Ostrzeżenie: aby uzyskać dane, nawet przy użyciu tej metody, można na przykład po prostu otworzyć konsolę JS w Chrome i wpisać:

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

Tylko reguły bezpieczeństwa bazy danych mogą chronić twoje dane.

Niemniej jednak ograniczyłem użycie mojego produkcyjnego klucza API do mojej nazwy domeny w następujący sposób:

  1. https://console.developers.google.com/apis
  2. Wybierz swój projekt Firebase
  3. Kwalifikacje
  4. W obszarze Klucze API wybierz klucz przeglądarki. Powinno to wyglądać tak: „ Klucz przeglądarki (automatycznie utworzony przez usługę Google)
  5. W „ Akceptuj żądania od tych kierujących HTTP (strony internetowej) ” dodaj adres URL aplikacji (exemple: projectname.firebaseapp.com/*)

Teraz aplikacja będzie działać tylko z tą konkretną nazwą domeny. Stworzyłem więc kolejny klucz API, który będzie prywatny dla rozwoju hosta lokalnego.

  1. Kliknij Utwórz poświadczenia> Klucz API

Domyślnie, jak wspomniał Emmanuel Campos, Firebase tylko białe listy localhosti twoja domena hostingowa Firebase .


Aby upewnić się, że nie opublikuję przez pomyłkę niewłaściwego klucza API, używam jednej z następujących metod, aby automatycznie użyć bardziej ograniczonego w produkcji.

Konfiguracja aplikacji Create-React

W /env.development:

REACT_APP_API_KEY=###dev-key###

W /env.production:

REACT_APP_API_KEY=###public-key###

W /src/index.js

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

Moja poprzednia konfiguracja dla pakietu Webpack:

Używam Webpacka do budowania mojej aplikacji produkcyjnej i wkładam mój klucz API dewelopera do mojego, index.htmltak jak zwykle. Następnie w moim webpack.production.config.jspliku zastępuję klucz za każdym razem, gdy index.htmlkopiowany jest do wersji produkcyjnej:

plugins: [
    new CopyWebpackPlugin([
      {
        transform: function(content, path) {
          return content.toString().replace("###dev-key###", "###public-key###");
        },
        from: './index.html'
      }
    ])
  ]
teraz
źródło
1
Czy to ci odpowiada? Myślałem o zrobieniu tego samego dla aplikacji na Androida. Zastanawiam się, dlaczego Firebase nie opisuje tego w dziale bezpieczeństwa.
steliosf
2
Do tej pory nie miałem problemu, ale prawdopodobnie również żadnych ataków
teraz
3
Nie jest to wspomniane w ich przewodniku, ponieważ nie ochroni cię przed skrobaniem. Wszystko to gwarantuje, że ktoś inny nie będzie mógł stworzyć aplikacji sieciowej, która używa bazy ogniowej do odczytu (lub zapisu) danych, jeśli działa ona w normalnej, dobrze zachowującej się przeglądarce.
thoutbeckers
@thoutbeckers masz rację, dziękuję. Zredagowałem odpowiedź, ale zrezygnowałem z tej metody, ponieważ nadal może być użyteczna.
teraz
1
@FrankvanPuffelen Z tego, co rozumiem, nie robi to dużej różnicy, ale może sprawić, że nieco bardziej denerwujące będzie nadużywanie twojego przydziału, ponieważ w dobrze zachowującej się przeglądarce klucz API podawany z HTML / JS będzie działał tylko zgodnie z przeznaczeniem domeny, a nie localhost lub cokolwiek innego. Ale zgadzam się, że dodatkowa ochrona jest marginalna w porównaniu z tym, co już zapewnia Firebase. Przeredaguję odpowiedź na coś mniej dramatycznego.
teraz
22

Nie jestem przekonany do ujawnienia kluczy bezpieczeństwa / konfiguracji klientowi. Nie nazwałbym tego bezpiecznym, nie dlatego, że ktoś może ukraść wszystkie prywatne informacje od pierwszego dnia, ponieważ ktoś może wysunąć nadmierną prośbę, wyczerpać twój przydział i sprawić, że będziesz winien Google dużo pieniędzy.

Musisz pomyśleć o wielu koncepcjach, od ograniczania ludzi do dostępu do miejsca, gdzie nie powinni być, ataków DOS itp.

Wolałbym, żeby klient najpierw trafił na twój serwer internetowy, tam umieścisz zaporę ogniową z pierwszej ręki, captcha, cloudflare, niestandardowe zabezpieczenia między klientem a serwerem lub między serwerem a bazą ogniową i jesteś gotowy. Przynajmniej możesz najpierw zatrzymać podejrzaną aktywność, zanim dotrze ona do bazy ogniowej. Będziesz miał znacznie większą elastyczność.

Widzę tylko jeden dobry scenariusz użycia dotyczący konfiguracji opartej na kliencie do zastosowań wewnętrznych. Na przykład masz domenę wewnętrzną i masz pewność, że osoby z zewnątrz nie będą miały do ​​niej dostępu, więc możesz skonfigurować środowisko takie jak przeglądarka -> typ bazy ogniowej.

Teoman Shipahi
źródło
10
Ale czy to nie to samo, co „ujawnianie” jakiegokolwiek innego interfejsu API REST? Mam na myśli, że z REST API URL jest dostępny dla użytkownika. Mogą używać adresu URL, aby wysyłać dowolne żądania i wyczerpać limit. Firebase robi konfigurację z kluczami API do identyfikacji części backendu i tak musi być i musi być dostępna dla użytkownika, aby mógł wysyłać żądania.
mbochynski
3
@mbochynski, ale możesz nieco wysyłać bezpośrednie żądania do zasobów, które powodują płacenie rachunku. A po stronie Firebase nie ma tylu mechanizmów kontrolnych, które zapobiegałyby atakom DDoS itp. Moją sugestią byłoby, aby Twój klient zadzwonił do twojego interfejsu API REST, ale ten interfejs API REST powinien przechowywać klucze API prywatnie, a nawet zanim trafisz zasoby Firebase, sprawdź je jeśli są to uzasadnione wnioski. (przez Cloudflare itp.). lub pobierz wyniki z pamięci podręcznej. Wtedy trafisz swoje zasoby Firebase tylko wtedy, gdy będziesz musiał. Właśnie to
wdrożyłbym
3
ujawnianie kluczy w przeglądarce jest poważnym złym pomysłem. ci, którzy napisali te wszystkie przewodniki / artykuły, co oni sobie myśleli? strona odsyłająca http dla bezpieczeństwa? łatwo to sfałszować
Nick Chan Abdullah
1
Nie myślicie o tym dobrze. Nie myśl o kluczu API jako tajemnicy; to nie jest klucz prywatny, to tylko identyfikator, więc Firebase API wie, kto ma dostęp do jakiego projektu. Jeśli chcesz dużo elastyczności i musisz kontrolować każdy etap interakcji serwer / klient, nie powinieneś używać Firebase, powinieneś używać GCP.
forresthopkinsa
@forresthopkinsa Mam powyższy link do komentarza, jakie podejście wybrać. Nikt tutaj nie jest na tyle naiwny, by sugerować, że jest to tajny klucz.
Teoman shipahi
4

Wierzę, że kiedy reguły bazy danych zostaną zapisane dokładnie, wystarczy chronić twoje dane. Ponadto istnieją wytyczne, które można zastosować, aby odpowiednio ustrukturyzować bazę danych. Na przykład utworzenie węzła UID pod użytkownikami i umieszczenie pod nim wszystkich informacji. Następnie musisz wdrożyć prostą regułę bazy danych, jak poniżej

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

Żaden inny użytkownik nie będzie mógł odczytać danych innych użytkowników, ponadto polityka domeny ograniczy żądania pochodzące z innych domen. Więcej na ten temat można przeczytać w zasadach bezpieczeństwa Firebase

Bhupiister singh
źródło
3

Ujawnienie klucza interfejsu API tworzy lukę, gdy włączona jest rejestracja użytkownika / hasła. Istnieje otwarty punkt końcowy interfejsu API, który pobiera klucz interfejsu API i umożliwia każdemu utworzenie nowego konta użytkownika. Następnie mogą użyć tego nowego konta, aby zalogować się do aplikacji chronionej uwierzytelnianiem Firebase lub użyć zestawu SDK do uwierzytelnienia przy użyciu hasła użytkownika / hasła i uruchamiania zapytań.

Zgłosiłem to do Google, ale mówią, że działa zgodnie z przeznaczeniem.

Jeśli nie możesz wyłączyć kont użytkowników / haseł, wykonaj następujące czynności: Utwórz funkcję w chmurze, aby automatycznie wyłączać nowych użytkowników na stronie Utwórz i utwórz nowy wpis DB, aby zarządzać ich dostępem.

Przykład: MyUsers / {userId} / Access: 0

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

Zaktualizuj swoje reguły, aby zezwolić na odczyty tylko użytkownikom z dostępem> 1.

Przy wyłączonej szansie funkcja nasłuchiwania nie wyłącza konta wystarczająco szybko, a reguły odczytu uniemożliwiają odczytanie jakichkolwiek danych.

bzk
źródło
3

Po przeczytaniu tego i po kilku badaniach dotyczących możliwości, wpadłem na nieco inne podejście do ograniczenia wykorzystania danych przez nieautoryzowanych użytkowników:

Zapisuję również moich użytkowników w mojej bazie danych (i tam zapisuję dane profilu). Więc właśnie ustawiłem reguły db tak:

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

W ten sposób tylko poprzedni zapisany użytkownik może dodawać nowych użytkowników do DB, więc nikt bez konta nie może wykonywać operacji na DB. dodawanie nowych użytkowników jest również możliwe tylko wtedy, gdy użytkownik ma specjalną rolę i edytuje tylko administrator lub sam użytkownik (coś takiego):

"userdata": {
  "$userId": {
    ".write": "$userId === auth.uid || root.child('/userdata/'+auth.uid+'/userRole').val() === 'superadmin'",
   ...
Berci
źródło
-2

Nie powinieneś ujawniać tych informacji. publicznie, specjalnie klucze API. Może to prowadzić do wycieku prywatności.

Przed upublicznieniem strony internetowej należy ją ukryć. Możesz to zrobić na 2 lub więcej sposobów

  1. Złożone kodowanie / ukrywanie
  2. Wystarczy umieścić kody SDK firebase na dole strony internetowej lub aplikacji, dzięki czemu firebase automatycznie wykona wszystkie czynności. nigdzie nie musisz umieszczać kluczy API
użytkownik12449933
źródło
1
Cytuję z Firebase: „Skopiuj i wklej te skrypty na dole tagu <body>, ale zanim skorzystasz z jakichkolwiek usług Firebase”, który zawiera klucz API
Luke-zhang-04