Firebase Realtime Database セキュリティ ルールを理解する

Firebase Realtime Database セキュリティ ルールでは、データベースへの読み取り / 書き込みアクセス権を持つユーザー、データが構造化される仕組み、存在するインデックスを決定します。これらのルールは Firebase サーバー上にあり、常時自動的に適用されます。読み取り / 書き込みリクエストはすべて、ルールで許可された場合にのみ実行されます。デフォルトで設定されるルールでは、他のユーザーがデータベースにアクセスすることは許可されていません。これによってデータベースは不正行為から保護されます。ルールをカスタマイズするか、認証を設定するまで、この保護は継続します。

Realtime Database セキュリティ ルールの構文は JavaScript と似ていて、次に示す 4 つの種類があります。

ルールの種類
.read ユーザーによるデータの読み取りを許可するときに記述します。
.write ユーザーによるデータの書き込みを許可するときに記述します。
.validate 値の適切なフォーマット方法、子属性を持つかどうか、およびデータ型を定義します。
.indexOn インデックスを作成する子に並べ替えとクエリをサポートするように指定します。

Realtime Database のセキュリティ概要

Firebase Realtime Database には、アプリのセキュリティを管理するための完全なツールセットが用意されています。これらのツールによって、ユーザーの認証、ユーザー権限の適用、入力内容の検証を簡単に実行できます。

Firebase のアプリは、その他多くの技術スタックを備えたアプリに比べて、クライアント側のコードを多く実行します。そのため、セキュリティにアプローチする方法が、場合によってこれまでとは少し異なります。

認証

通常、アプリを保護する最初の手順はユーザーの識別です。このプロセスを「認証」と言います。Firebase Authentication を使用すると、アプリへのログインをユーザーに許可できます。Firebase Authentication は、Google や Facebook などの一般的な認証方法に加え、メールとパスワードでのログインや匿名ログインなどもサポートします。

ユーザー ID はセキュリティの重要なコンセプトです多様なユーザーがさまざまなデータを持ち、場合によっては多様な機能も持っています。たとえば、チャット アプリケーションでは、メッセージがそれぞれ作成したユーザーに関連付けられています。ユーザーは、自分のメッセージは削除できますが、他のユーザーが投稿したメッセージは削除できません。

承認

ユーザーの識別はセキュリティの一部にすぎません。ユーザーを識別したら、データベース内のデータに対するユーザーのアクセス権を制御する方法が必要になります。Realtime Database セキュリティ ルールによって、ユーザーごとにアクセス権を制御できます。たとえば、次のセキュリティ ルールセットでは、あらゆるユーザーがパス /foo/ を読み取ることはできますが、どのユーザーもこれに書き込むことはできません。

{
  "rules": {
    "foo": {
      ".read": true,
      ".write": false
    }
  }
}

.read.write のルールはカスケード式に適用されます。そのため、このルールセットはパス /foo/ にあるあらゆるデータの読み取りアクセス権を付与するだけでなく、/foo/bar/baz のようなより深いパスにあるデータの読み取りアクセス権も付与します。データベース内の浅いパスにある .read.write のルールは、深いパスにあるルールよりも優先されるため、この例では、パス /foo/bar/baz のルールが false と評価されても、/foo/bar/baz への読み取りアクセス権は付与されます。

Realtime Database セキュリティ ルールには組み込み変数と関数が含まれています。これにより、他のパス、サーバー側のタイムスタンプ、認証情報などを参照できます。認証ユーザーに /users/<uid>/ への書き込みアクセス権を付与するルールの例を次に示します。ここで <uid> は、Firebase Authentication によって取得されたユーザーの ID です。

{
  "rules": {
    "users": {
      "$uid": {
        ".write": "$uid === auth.uid"
      }
    }
  }
}

データの検証

Firebase Realtime Database はスキーマレスです。開発時の変更はこれで容易になりますが、アプリの配布準備ができてからは、データの一貫性が重要になります。ルール言語に含まれる .validate ルールでは、.read ルールや .write ルールと同じ式によって検証ロジックを適用できます。唯一の違いは、検証ルールはカスケード式に適用されないことです。そのため、書き込みを許可するには、関連するすべての検証ルールの評価が true でなければなりません。

このルールにより、/foo/ に書き込まれるデータは 100 文字未満に制限されます。

{
  "rules": {
    "foo": {
      ".validate": "newData.isString() && newData.val().length < 100"
    }
  }
}

検証ルールでは、.read ルールや .write ルールと同じ組み込み関数や変数のすべてにアクセス権があります。これらを使用して、データベース内の他の場所にあるデータ、ユーザー ID、サーバー時間などを認識する検証ルールを作成できます。

データベース インデックスの定義

Firebase Realtime Database ではデータの並べ替えとクエリを実行できます。データサイズが小さい場合、データベースがアドホック クエリをサポートしているため、通常、開発時にインデックスは必要ありません。ただしアプリを起動する前に、アプリの規模が拡大してもクエリが引き続き機能するように、クエリにインデックスを指定しておくことが重要です。

インデックスは .indexOn ルールで指定します。恐竜リストの体高フィールドと体長フィールドのインデックスを作成するインデックス宣言の例を次に示します。

{
  "rules": {
    "dinosaurs": {
      ".indexOn": ["height", "length"]
    }
  }
}

次のステップ