【徹底解説】Firebaseのセキュリティルールとは何か?仕組みやどこに書くか・書き方を実例で解説(service cloud.firestore, request.auth, match, firestore.rules or firebase.rules)

firebase-prograshi(プロぐらし)-kv Firebase
記事内に広告が含まれていることがあります。

Firebaseでアプリを公開する際、最も重要かつ初心者が挫折しやすい壁が「セキュリティルール」です。

もし設定を誤れば、大切なデータが全世界に公開されたり、逆に誰も読み書きできなくなったりするリスクがあります。

しかし、その仕組みを一度理解してしまえば、これほど強力で頼もしい味方はありません。

本記事では、「そもそもセキュリティルールとは何か?」という基本から、request.auth を使ったログイン判別や match による階層指定など、実務で必須となる書き方を実例付きで解説しています。

また、意外と迷いやすい「firestore.rulesfirebase.rules の違い」や「どこに書くのが正解か」といった運用面の疑問にも答えています。

この記事を読み終える頃には、あなたのアプリを安全に守るための「鉄壁のルール」が自力で書けるようになっているはずです!

  1. セキュリティルールとは何か?
  2. セキュリティルールの仕組み
    1. 認証と許可
    2. セキュリティルールを使った処理の流れ
  3. セキュリティルールはどこに設定するか?
  4. セキュリティルールは公開していもいい ※注意点あり
    1. セキュリティルールを公開してもいい理由
    2. 公開時の絶対条件
  5. セキュリティルール関係の通知
  6. 【例外】Admin SDKはセキュリティルールを無視できる
  7. セキュリティルールの書き方
    1. 基本構文
    2. rules_version = ‘2’;
    3. service cloud.サービス { … }
    4. match /databases/{database}/documents { … }
    5. match コレクション/ドキュメントID (パスの指定)
    6. allow 操作: if 条件;
    7. allowの操作の種類
    8. request.auth(ログイン状態)
  8. よく使うルール
    1. 全員禁止(完全にロック)
    2. ログインしている人のみ
    3. 自分のデータのみ
    4. 編集は許可、作成・削除は不可
    5. フィールドの指定(resource.data、request.resource.data)
  9. matchの適用順位(上から順ではない)
  10. (実例1)Firebaseコンソールに直接書く方法
  11. (実例2)ローカルファイル(firestore.rules)を作成し、firebase CLIでデプロイする
    1. Firebaseコンソールのルールを上書きする
    2. ファイルはサービス毎に分ける
    3. 【手順0】Firebase CLIの導入とfirebase init
    4. 【手順1】firestore.rulesファイルを作成する
    5. 【手順2】ルールを記述する
    6. 【手順3】デプロイする
    7. (補足)Firebaseコンソールでの確認

セキュリティルールとは何か?

セキュリティルールとはFirebase側(サーバー側)の機能で、データへのアクセスや読み書きの権限を制御するためのルールです。

通常、従来の開発(RailsやNode.jsなど)では、サーバーサイドに「このユーザーは管理者か?」といったチェック処理を自分で書きます。しかし、Firebase(FirestoreやStorage)はクライアント(ブラウザ)から直接データベースを操作できるという特徴があります。

もしルールを設定していないと、悪意のあるユーザーがブラウザのコンソールから「他人のデータを削除する」「全データを書き換える」といったことが簡単にできてしまいます。これを防ぐのがセキュリティルールです。

なぜFirebase側に設定するか?

セキュリティルールがNext.jsなどのブラウザ側にあると、悪意のあるユーザーに簡単に書き換えられてしまいます。

Firebase側に設定することで、ブラウザ側からどんなに不正なリクエストを送ってもシャットアウトすることができます。

  • ブラウザ(Next.js): ユーザーが中身を自由に見たり、改ざんしたりできる場所。
  • Firebase(サーバー): Googleが管理する安全な場所。


セキュリティルールの仕組み

認証と許可

セキュリティールールは大きく分けて「認証」と「認可」という2つの条件があります

認証(Authentication)は、ユーザーの管理で、アクセスしている人が誰かを管理するものです。

認可(Authorization)は、アクセスしているユーザーがどのデータにアクセスできるかや、読み書きの権限がどこまであるかを管理するものです。

注意点

セキュリティールールはFirebaseのサービス毎に書き方が違います。

※FirestoreとStorageのルールは独自DSL(rules言語)なのに対し、Realtime DatabaseのルールはJSON形式となっており、書き方が大きく異なります。


セキュリティルールを使った処理の流れ

例えば、ブラウザ経由でFirestoreのデータを保存する流れは以下のようになります。

  1. ユーザーがブラウザ(Next.js)の保存ボタンをクリックする。
  2. Firebase Authがログイン中のユーザーが誰かという証明書を発行する。
  3. 届いたリクエストと証明書を見て、Firebaseのセキュリティルールで権限を確認する
  4. ユーザーに対象のデータの書き込み権限がある場合、Firestoreにデータを保存する。
ブラウザ(Next.js)>  Auth  >  セキュリティルール  >  Firestore


セキュリティルールはどこに設定するか?

Firebaseのセキュリティルールの設定場所は2つあります。

Firebaseのセキュリティルールの設定場所
  1. Firebaseコンソールに直接書く
  2. ローカルファイル(firebase.rules)を作成し、firebase CLIでデプロイする

具体的なやり方は下の方で解説しています。

セキュリティルールは公開していもいい ※注意点あり

セキュリティルールを公開してもいい理由

ローカルファイル(firebase.rules)を作成する場合、セキュリティルールの内容をGitで管理することができます。

セキュリティルールは必ずしも公開する必要はありませんが、公開しているプロジェクトも多くあります。

セキュリティルールを悪意のある人が知っていたとしても、本人としてログイン(認証)できない限り、データは盗めません。

MEMO

セキュリティルールを公開するとは「この家は頑丈な鍵がかかっています」という家の設計図を公開しているようなものです。

公開する必要はない(時と場合に応じて)

セキュリティルールは公開してもいいですが、公開しなくてもいいです。必要に応じてGitなどの管理ツールに含めてチームで共有します。


公開時の絶対条件

セキュリティルールを公開するにあたって「万が一、ルールの内容が他人に知られたとしても、それだけでセキュリティが破られるような脆弱なものであってはならない」という絶対条件があります。

例えば、以下のようにセキュリティルールの中にパスワードを記述するのは絶対NGです。

//パスワードが書いてある
allow write: if request.resource.data.secret_code == "my-secret-123";

 ↓ 以下のように認証に基づいて管理します。

// 「Googleログインした本人のみ」という仕組みを使う
allow write: if request.auth.uid == userId;


セキュリティルール関係の通知

セキュリティルールが「ない/不備がある/厳しすぎる」とGoogleからメールが来ることがあります。そういった場合、プロジェクトが以下のような状態になっていることがほとんどです。

なぜ通知が来るか?
  • テストモード(全公開): 誰でも読み書きし放題。非常に危険。
  • ロックモード(全拒否): 誰も読み書きできない。アプリが動かない。

ルールを放置して「全公開」のままにしておくと、データベースの中身をすべて消されたり、個人情報を抜き取られたりするリスクがあります。


【例外】Admin SDKはセキュリティルールを無視できる

Firebase Admin SDKは、特権(管理者権限)を持ってFirebaseを操作するための開発キットです。

Admin SDKを使うと、セキュリティルールを無視してデータのアクセスや書き込み・削除をすることができます


セキュリティルールの書き方

基本構文

セキュリティルールの基本構文は以下のようになっています。

これは、Firestoreのusersコレクションのデータ(ドキュメント)の読み書きができるのはログインしているユーザーのみと指定しています。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    match /users/{userId} {
      allow read, write: if request.auth != null;
    }

  }
}

なお、本人のデータのみ操作できるようにする(他人のデータはいじれない)ようにするには、 allowの ifを以下のように変更します。

match /users/{userId} {
  allow read, write: if request.auth.uid == userId;
}


rules_version = ‘2’;

Firebaseのセキュリティルールのバージョン2を利用することの宣言です。(※個人的に管理するバージョンではありません)

必ず記述します


service cloud.サービス { … }

service cloud.サービス { … }

serviceでどのサービスに対するセキュリティルールかを指定します。

firestore用のルールを記述する場合は以下のように記述します。

service cloud.firestore { ... }

対象のサービス毎にルールを記述します。

サービス書き方
Firestoreservice cloud.firestore
Storageservice firebase.storage
Realtime DBservice firebase.database


match /databases/{database}/documents { … }

match /databases/{database}/documents { … }

Firestoreの全てのドキュメントへのセキュリティルールを記述します。

{database}は全てのデータベース

match /databases/{database}/documentsの「{database}」は全てのデータベースを指定しています。

{ }の中の文字列に指定はありません。{ anything }や{db} でも同じです。(※ただし、ほぼ必ず{database}と書きます)

実際に入る値は (default) が入ります。

match /databases/{database}/documents

 ↑↓ 同じ

match /databases/(default)/documents


match コレクション/ドキュメントID (パスの指定)

match /users/{userId}

matchでアクセス先のパスを指定します。ここでは、usersコレクションの全てのドキュメントを指定しています。

{userId}はusersコレクションの全てのデータを意味しています

{userId}はドキュメントID

ここの{userId}はフィールドのuserIdではなく、ドキュメントIDです。

users(コレクション)
 ├ abc123(ドキュメントID)
 │   ├ name: "Taro"
 │   └ userId: "abc123"
 └ xyz999(ドキュメントID)
     ├ name: "Hanako"
     └ userId: "xyz999"


フロントからドキュメントを取得する際は以下のようにドキュメントIDを指定します。ここの値が該当します。

getDoc(doc(db, "users", "abc123"));


allow 操作: if 条件;

allow 操作: if 条件;

allowで何をしていいかを記述します。


allow read, write: if request.auth != null;

if request.auth != null;なので、ログインしている人ならデータの読み書きが可能(allow read, write:)というルールです。


allowの操作の種類

allow 操作:で指定する種類には以下があります。

allowの操作の種類
  1. read: 読込み
  2. write: 作成・更新・削除(create + update + delete)
  3. create: 新規作成
  4. update: 更新
  5. delete: 削除

「write = create + update + delete」の操作となります。


request.auth(ログイン状態)

request.authはログインしているユーザーの場合にtrue、ログインしていない場合はfalseとなります。


よく使うルール

全員禁止(完全にロック)

allow read, write: if false;

例えば、全ドキュメントへのアクセスを禁止(firestoreをロック)する場合は以下のように記述します。

match /databases/{database}/documents {
  match /{document=**} {
    allow read, write: if false;
  }
}
「=**」は無限階層を表す

{document=** }のdocumentは変数なので指定はありません。「=**」が特に重要で、配下の階層も全て含むという意味になります。


ログインしている人のみ

allow read, write: if request.auth != null;


自分のデータのみ

allow read, write: if request.auth.uid == userId;


編集は許可、作成・削除は不可

match /users/{userId} {
  allow read: if request.auth.uid == userId;
  allow update: if request.auth.uid == userId;
  allow create: if false;
  allow delete: if false;
}


フィールドの指定(resource.data、request.resource.data)

フィールドを直接指定するには「resource.data」と「request.resource.data」を使います。

フィールドの指定
  1. フィールドの値: resource.data
  2. 更新後のフィールドの値: request.resource.data


useIdの初回登録は許可するが、書き換えは許可しない場合は以下のようにします。

allow update: if
  request.auth.uid == resource.data.userId &&
  request.resource.data.userId == resource.data.userId;


matchの適用順位(上から順ではない)

セキュリティルールの適用は上から順ではありません

順番は関係なく、一番具体的なmatchが使われます

match /users/{userId} { ... }
match /users/admin { ... }


(実例1)Firebaseコンソールに直接書く方法

Firebaseコンソールにアクセスし、セキュリティルールを追加したいサービスを選択します。

上部の「ルール」タブをクリックして、ルールを記述します。

なおデフォルトでは以下のようになっています。

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {

    // This rule allows anyone with your Firestore database reference to view, edit,
    // and delete all data in your Firestore database. It is useful for getting
    // started, but it is configured to expire after 30 days because it
    // leaves your app open to attackers. At that time, all client
    // requests to your Firestore database will be denied.
    //
    // Make sure to write security rules for your app before that time, or else
    // all client requests to your Firestore database will be denied until you Update
    // your rules
    match /{document=**} {
      allow read, write: if request.time < timestamp.date(2026, 2, 12);
    }
  }
}
説明文の内容

説明には以下のように記載されています。

// このルールにより、Firestore データベースへの参照を持つすべてのユーザーが、Firestore データベース内のすべてのデータを表示、編集、削除できるようになります。これは、アプリを攻撃者に無防備にしてしまうため、
// 30 日後に期限切れになるように設定されています。期限が切れると、Firestore データベースへのすべてのクライアント
// リクエストが拒否されます。
//
// 期限が切れる前にアプリのセキュリティ ルールを記述してください。そうしないと、ルールを更新するまで、Firestore データベースへのすべてのクライアント リクエストが拒否されます。


match /{document=**} {
  allow read, write: if request.time < timestamp.date(2026, 2, 12);
}

matchの指定が「/{document=**}」となっています。

これは、このパス配下の すべてのドキュメント にマッチするという最強のワイルドカードです。

「document」の部分は変数名で、他の名前でも問題ありません。大事なのは「=**」です。

「=**」は無限階層を表す

「=*」のみだと0階層(対象の階層のみ)ですが、「=**」の場合は、配下の階層も全て含みます。


(実例2)ローカルファイル(firestore.rules)を作成し、firebase CLIでデプロイする

ローカルファイルを作成し、firebase CLIでデプロイする方法も使えます。


Firebaseコンソールのルールを上書きする

ローカルファイル(firestore.rules)を作成し、firebase CLIでデプロイした場合、Firebaseコンソールの「ルール」の中のコードを上書きします

注意点

Firebaseコンソールが無視されるというわけではなく、最後にデプロイまたは保存したものが最終版として適用されます。


ファイルはサービス毎に分ける

セキュリティルール用のファイルはサービス毎に分けて作成します

★firebase initで対象のサービスを選択したときに、生成されます。

ファイル名
  • firestore.rules(Firestore用のルール)
  • storage.rules(Cloud Storage用のルール)
  • database.rules.json(Realtime DB用のルール)

特定のサービスしか使わないならルートディレクトリにそのままファイルを作成します。

中~大規模なプロジェクトであれば「rules」といったディレクトリを作成し、その中にファイルを作成することもあります。その場合は、firebase.jsonでファイルパスを合わせる必要があります。


firebase.rulesは使わない

「firebase.rules」というファイルを1つ作って、その中に複数のサービスのルールを記述することもできますが推奨ではありません。


database.rules.jsonだけjson形式な理由

Realtime DatabaseはFirebaseで最も古いサービスで当時からJSONで記述していたため、現在もそのルールが適用されています。

一方、FirestoreやStorageはFirebase独自のDSL(rules言語)が使われています。

それぞれで書き方も大きく異なります。


【手順0】Firebase CLIの導入とfirebase init

セキュリティルールをデプロイするにはFirebase CLIが必須です。

また、firebase initでプロジェクトフォルダでFirebase CLIを使う設定を済ませておく必要があります。

詳細については下記をご参考ください。


【手順1】firestore.rulesファイルを作成する

ルートディレクトリにrulesディレクトリを作成し、その中にfiresotre.rulesを作成します。

mkdir rules
ni rules/firestore.rules


【手順2】ルールを記述する

作成したファイルにルールを記述します。

ここでは、usesコレクションのデータはログイン中のユーザーかつ、自分のデータしかいじれないように制限をかけます。

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    
    //usersコレクションは自分のデータのみ編集可能
    match /users/{userId} {
      allow read, write: if request.auth.uid == userId;
    }
  }
}


【手順3】デプロイする

firestoreのルールのみをデプロイします。

firebase deploy --only firestore:rules


Deploy completeと表示されれば反映は完了です。


内容が同じ場合はスキップされる

なお、ルールの内容がFirebaeコンソールと全く同じ場合、アップロードはスキップされます。(下記の「already up to date, skipping upload…」の部分)

※エディタで編集して保存(ctrl + s)せずにdeployしたときに発生しがちです


(補足)Firebaseコンソールでの確認

Firebaseコンソールで確認すると、ローカルで作成したfirestore.rulesの内容に置き換わっていることがわかります。

タイトルとURLをコピーしました