Firebase apiKeyを公開しても安全ですか?


439

FirebaseのWebアプリガイドは、私が与えられ置くべきと述べapiKeyFirebaseを初期化するために、私のHTMLで:

// 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はすべての訪問者に公開されます。そのキーの目的は何ですか?それは本当に公開することを意図していますか?


1
Firebase AuthFirebaseデータベースのルールを設定している限り、その情報を公開できます
abbaf33f

ユーザーChristophe Quintardが、Firebase APIのセキュリティに関する追加情報を含む非常に役立つ記事へのリンクを追加したので、ここに再投稿します。品質が低いため削除のフラグが付けられた回答)
Oliver Schafeld

この特定のフレームワークがたまたまそのAPIを公開しても問題ないからといって、他のフレームワークがそれで問題ないということではありません。一般的に「APIキーを公開しても大丈夫」という考えを持って、誰もこの投稿から離れることを望まないでしょう。
YungGun

問題なくキーを公開します。安全にするために、本番環境の特定のドメインで制限して、他の誰もランダムなドメイン名からAPIを呼び出せないようにすることができます。より安全にするために、実稼働アプリからlocalhostを削除します。
BLΛCK

1
リファラーのホワイトリストからlocalhostを削除しても、テストが困難になる以外は何もできないと思います。この構成は、IPホワイトリストのようなものではありません。CORS構成のように考えてください。Firebaseの仕組みは、これらのAPIルートがクライアントから直接呼び出されることであり、プロキシされません。そのため、ウェブページにはAPIキーが必要です。悪役がPostmanからAPIルートを呼び出したい場合、参照元のホワイトリストはそれらを阻止しません。これは、他のパブリックサイトがサーバーをむちゃくちゃにするのを防ぐためにのみ役立ちます。
フォレストホプキンサ

回答:


451

この構成スニペットのapiKeyは、Googleサーバー上のFirebaseプロジェクトを識別するだけです。誰かがそれを知っていることは、セキュリティ上のリスクではありません。実際、Firebaseプロジェクトとやり取りするためには、それを知る必要があります。この同じ構成データは、Firebaseをバックエンドとして使用するすべてのiOSおよびAndroidアプリにも含まれています。

その意味で、同じスニペットでプロジェクトに関連付けられているバックエンドデータベースを識別するデータベースURLと非常に似ていますhttps://<app-id>.firebaseio.com。これがセキュリティリスクではない理由については、この質問を参照してください:Firebaseデータの変更を制限する方法?、Firebaseのサーバー側のセキュリティルールを使用して、承認されたユーザーのみがバックエンドサービスにアクセスできるようにします。

Firebaseバックエンドサービスへのすべてのデータアクセスを認証する方法を学びたい場合は、Firebaseセキュリティルールに関するドキュメントをご覧ください


この構成データをバージョン管理にコミットするリスクを軽減したい場合は、Firebase HostingのSDK自動構成の使用を検討してください。キーは同じ形式でブラウザーに残りますが、それによってコードにハードコードされなくなります。


7
それでは、他の人が私のfirebaseデータベースのすべてのデータにアクセスできるということですか?
Emmanuel Campos 2016年

31
@EmmanuelCampos回答は「はい」と「いいえ」です。他の人にデータベース内のすべてのデータへのアクセスを許可または許可する場合は、はい。そして、いいえ、あなたが彼らに望まないなら。Firebaseデータベースにはルール、
ユーザー

5
私の最後の質問support.google.com/firebase/answer/6400741の回答をここに見つけました。助けてくれてありがとう。このリンクは将来誰かを助けるかもしれません。
Emmanuel Campos 2016年

7
@ m.rufcaの場合、認証されたユーザーがデータを使用できる必要があります。そしてここにトリックがあります。デフォルトでは、firebase設定ではlocalhostとプロジェクトドメインのみが認証を実行することを許可されています。そのため、通常はFirebaseで動作するアプリを他の誰も作成できません。
アルテム・アルヒポフ2017

15
ボットが私のアプリで無制限のユーザーを作成している場合はどうなりますか?どうすればキャプチャを要求できますか?
Muhammad Umer 2017年

79

ここでプルフロフロとフランクファンプフェレンの回答を基に、スクレイピングを妨げないこの設定をまとめましたが、APIキーの使用が少し難しくなる可能性があります。

警告:この方法でもデータを取得するには、たとえば、ChromeでJSコンソールを開いて次のように入力します。

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

データを保護できるのは、データベースセキュリティルールだけです。

それにもかかわらず、私は次のように私のプロダクションAPIキーの使用を私のドメイン名に制限しました:

  1. https://console.developers.google.com/apis
  2. Firebaseプロジェクトを選択します
  3. 資格情報
  4. APIキーの下で、ブラウザーキーを選択します。これは次のようになります。「ブラウザキー(Googleサービスによって自動作成)
  5. 「では、これらのHTTPリファラ(ウェブサイト)からの要求を受け入れる」、あなたのアプリ(exemple:のURLを追加しますprojectname.firebaseapp.com/*

これで、アプリはこの特定のドメイン名でのみ機能します。そこで、localhost開発用にプライベートになる別のAPIキーを作成しました。

  1. [認証情報を作成]> [APIキー]をクリックします

Emmanuel Camposが述べたように、デフォルトでは、FirebaseはホワイトリストlocalhostとFirebaseホスティングドメインのみをリストします


間違ったAPIキーを誤って公開しないようにするために、次のいずれかの方法を使用して、制限の厳しいものを自動的に本番環境で使用します。

Create-React-Appのセットアップ

/env.development

REACT_APP_API_KEY=###dev-key###

/env.production

REACT_APP_API_KEY=###public-key###

/src/index.js

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

以前のWebpackのセットアップ:

私はWebpackを使用して本番アプリをビルドし、通常どおりに開発APIキーを内部に配置index.htmlします。次に、webpack.production.config.jsファイル内で、index.html本番ビルドにコピーされるたびにキーを置き換えます。

plugins: [
    new CopyWebpackPlugin([
      {
        transform: function(content, path) {
          return content.toString().replace("###dev-key###", "###public-key###");
        },
        from: './index.html'
      }
    ])
  ]

1
それで問題ありませんか?Androidアプリでも同じことをしようと考えていました。なぜFirebaseがセキュリティセクションでそれをカバーしていないのでしょうか。
steliosf 2017年

2
私はどちらかのこれまでのところ何も問題がなかったが、おそらく何も攻撃しました
今、

3
これはあなたをこすることからあなたを保護しないので彼らのガイドでは言及されていません。これにより、Firebaseを使用してデータを読み取り(または書き込み)するWebアプリを他の誰かが通常の正常に動作するブラウザーで実行すると作成できなくなります。
thoutbeckers 2017

@thoutbeckersありがとうございます。回答を編集しましたが、それでもまだ役に立つかもしれないので、メソッドを残しました。
今、

1
@FrankvanPuffelen私が理解していることから、大きな違いはありませんが、正常に動作するブラウザでは、HTML / JSで提供されるAPIキーが意図したものでのみ機能するため、割り当てを悪用することで少し面倒になる可能性がありますlocalhostなどではなく、ドメイン。しかし、追加された保護は、Firebaseがすでに提供しているものに比べてわずかであることに同意します。それほど劇的でないものへの答えを書き直します。
現在

22

セキュリティ/構成キーをクライアントに公開することに確信が持てません。誰かが最初の日からすべての個人情報を盗むことができるため、誰かが過度のリクエストを行い、割り当てを使い果たして、Googleに多額の金を借りさせることができるからではありません。

DOS攻撃など、人々が本来あるべき場所にアクセスできないように制限することから、多くの概念を考える必要があります。

私はクライアントが最初にあなたのウェブサーバーにぶつかることをもっと望みます、そこであなたは今までにないファイアウォール、キャプチャ、クラウドフレア、カスタムセキュリティをクライアントとサーバーの間、またはサーバーとファイアベースの間に置いて、あなたは行ってもいいです。少なくとも、疑わしいアクティビティをFirebaseに到達する前に停止することができます。はるかに柔軟性があります。

内部使用のためにクライアントベースの構成を使用するための1つの適切な使用シナリオのみが表示されます。たとえば、内部ドメインがあり、外部の人がそこにアクセスできないことを確信しているので、ブラウザのような環境をセットアップできます-> firebase type。


10
しかし、それは他のREST APIを「公開」することと同じではありませんか?つまり、REST APIを使用すると、ユーザーはURLを使用できます。URLを使用して、必要なリクエストを行い、割り当てを使い果たすことができます。Firebaseが行うことは、バックエンドの一部を識別するためにAPIキーを使用してconfigを使用することであり、それはユーザーがリクエストを行うために利用可能でなければなりません。
mbochynski

3
@mbochynskiですが、リソースを直接要求して、請求を支払うことができます。Firebase側では、DDoS攻撃などを防ぐための制御メカニズムはそれほど多くありません。クライアントがREST APIを呼び出せるようにするが、REST APIはAPIキーを非公開で保持し、Firebaseリソースにアクセスする前でも、それらを検証することをお勧めしますそれらが正当な要求である場合。(Cloudflareなどを介して)。またはキャッシュから結果を取得します。その後、必要な場合にのみFirebaseリソースにアクセスします。これは私が実装し何であるfirebase.google.com/docs/admin/setup
テオーマンshipahi

3
ブラウザでキーを公開することは非常に悪い考えです。これらすべてのガイド/記事を書く人、彼らは何を考えていましたか?セキュリティのためのhttpリファラー?なりすましが容易
Nick Chan Abdullah

1
君たちはこの権利について考えていない。APIキーを秘密と考えないでください。これは秘密鍵ではなく、単なるIDであるため、Firebase APIは誰がどのプロジェクトにアクセスしているかを認識します。多くの柔軟性が必要で、サーバーとクライアントの相互作用のすべてのステップを制御する必要がある場合は、Firebaseを使用するのではなく、GCPを使用する必要があります。
フォレストホプキンサ

@forresthopkinsa私は上記のリンクにどのようなアプローチを取るかコメントしています。ここには誰も、それが秘密鍵であることを示唆するほど単純ではありません。
Teoman Shipahi

4

データベースのルールが正確に記述されれば、データを保護するのに十分だと私は信じています。さらに、それに応じてデータベースを構造化するために従うことができるガイドラインがあります。たとえば、ユーザーの下にUIDノードを作成し、その下にすべての情報を配置します。その後、以下のような単純なデータベースルールを実装する必要があります。

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

他のユーザーは他のユーザーのデータを読み取ることができません。さらに、ドメインポリシーは他のドメインからのリクエストを制限します。Firebaseセキュリティルールで詳細を読むことができ ます


3

ユーザー/パスワードのサインアップが有効になっている場合、APIキーの公開により脆弱性が生じます。APIキーを受け取り、誰でも新しいユーザーアカウントを作成できるようにするオープンAPIエンドポイントがあります。次に、この新しいアカウントを使用してFirebase Authで保護されたアプリにログインするか、SDKを使用してユーザー/パスで認証し、クエリを実行します。

これをGoogleに報告しましたが、意図したとおりに機能しているとのことです。

ユーザー/パスワードアカウントを無効にできない場合は、次の操作を行う必要があります。新しいユーザーを自動的に無効にするクラウド機能を作成し、そのユーザーのアクセスを管理する新しいDBエントリを作成します。

例:MyUsers / {userId} / Access:0

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

ルールを更新して、アクセスが1より大きいユーザーのみに読み取りを許可します。

オフのチャンスでは、リスナー関数がアカウントを十分に速く無効にしないため、読み取りルールによってデータを読み取ることができなくなります。


3

これを読んだ後、可能性についていくつかの調査を行った後、権限のないユーザーによるデータの使用を制限するために、少し異なるアプローチを考え出しました。

私も自分のDBにユーザーを保存します(そしてプロファイルデータをそこに保存します)。だから私はこのようにdbルールを設定するだけです:

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

この方法では、以前に保存されたユーザーのみが新しいユーザーをDBに追加できるため、アカウントを持たないユーザーがDBで操作を実行することはできません。また、新しいユーザーの追加は、ユーザーに特別な役割があり、管理者またはそのユーザー自身(次のようなもの)のみが編集できる場合にのみ可能です。

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

-2

この情報は公開しないでください。公開では、特にapiキー。プライバシーの漏洩につながる可能性があります。

Webサイトを公開する前に、非表示にする必要があります。あなたは2つ以上の方法でそれを行うことができます

  1. 複雑なコーディング/非表示
  2. Firebase SDKコードをウェブサイトまたはアプリの下部に配置するだけで、Firebaseがすべて自動的に機能します。APIキーをどこにも置く必要はありません

1
私はFirebaseから、「これらのスクリプトをコピーして<body>タグの下部に貼り付けますが、Firebaseサービスを使用する前に」APIのキーを含みます
Luke-zhang-04
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.