【Security Rules入門】画面側だけでなくFirestore側でデータを守る
このページでやること
このページでは、Firestore Security Rulesの考え方を学びます。
今までのページでは、Flutter側でこのような制御をしてきました。
ownerだけ権限変更できる
admin以上だけタスク削除できる
viewerは見るだけ
ただし、Flutter側の制御だけでは、本番アプリとしては不十分です。
Firestore側にもルールを書いて、データそのものを守る必要があります。
今日のゴール
Firestore Security Rulesの役割を理解します。
Flutter側
↓
ボタンを隠す
操作前にチェックする
分かりやすいエラーを出す
Firestore Rules側
↓
本当にデータを守る
不正な読み書きを止める
このページでは、まず入門として「ログインしている人だけ読み書きできる」ルールに変更します。
npmや環境変数は必要?
このページでは、npmは使いません。
環境変数も設定しません。
Firebase ConsoleでFirestore Rulesを書き換えます。
Firebase Consoleを開く
↓
Firestore Databaseを開く
↓
ルールを開く
↓
Security Rulesを書く
↓
公開する
Step 1:なぜSecurity Rulesが必要なのか
たとえば、Flutter側でこう書いていたとします。
viewerはタスク削除ボタンを押せない
これは画面上では有効です。
でも、Firestore側に制限がないと、アプリ画面を通さずにデータを書き換えられる可能性があります。
そのため、本番では必ずFirestore Rulesを書きます。
画面側の制御
↓
使いやすさのため
Firestore Rules
↓
本当の防御
Step 2:現在の開発用ルールを確認する
これまで学習用として、次のようなルールを使っていたかもしれません。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
これは、すべての読み書きを許可するルールです。
誰でも読める
誰でも書ける
誰でも削除できる
学習中の確認には便利ですが、本番公開では危険です。
Step 3:Firebase Consoleを開く
ブラウザでFirebase Consoleを開きます。
https://console.firebase.google.com/
今回のFlutterアプリで使っているプロジェクトを選びます。
プロジェクトが分からない場合は、Flutter側のこのファイルを確認します。
lib/firebase_options.dart
中に projectId が書かれています。
Step 4:Firestore Rules画面を開く
Firebase Consoleで、次の順番で進みます。
Build
↓
Firestore Database
↓
Rules
日本語表示の場合は、次のような表記です。
構築
↓
Firestore Database
↓
ルール
ここに、Firestoreのアクセスルールを書きます。
Step 5:まずはログイン必須ルールにする
最初の入門ルールとして、ログインしている人だけ読み書きできるようにします。
Rules画面に、次のコードを入れます。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
意味はこうです。
request.auth != null
↓
ログインしている人だけOK
未ログインの人は、Firestoreを読んだり書いたりできません。
Step 6:公開する
Rulesを書いたら、公開します。
Firebase Consoleの画面で、次のボタンを押します。
公開
英語表示の場合は、次のボタンです。
Publish
公開すると、すぐにアプリ側に反映されます。
Step 7:request.authとは?
request.auth は、ログイン中のユーザー情報です。
ログインしている場合は、中に情報があります。
request.auth != null
ログインしていない場合は、空です。
request.auth == null
つまり、次のように判断できます。
ログイン中 → 読み書きOK
未ログイン → 読み書きNG
Step 8:アプリで確認する
アプリを起動します。
flutter run
ログインしている状態で、次を確認します。
チーム一覧が見える
タスク一覧が見える
メンバー一覧が見える
タスク作成できる
ログイン中なら、今まで通り動けばOKです。
Step 9:未ログイン状態で確認する
一度ログアウトします。
ログアウト
未ログイン状態では、基本的に LoginPage が表示されます。
この状態で、Firestoreのデータ取得はできません。
ログイン前にFirestoreを読もうとすると、次のようなエラーになります。
permission-denied
これは、ルールが効いている証拠です。
Step 10:usersの基本ルールを考える
今のルールは、ログインしていれば全部読める状態です。
次に、本番に近づけるなら、users はこう考えます。
自分のユーザー情報だけ読める
自分のユーザー情報だけ書ける
Firestoreの場所はここです。
users/{uid}
ルールの考え方はこうです。
request.auth.uid == uid
意味は、自分のuidと、見ようとしているユーザードキュメントのuidが同じならOKです。
Step 11:usersだけ少し安全にする例
入門として、users だけ自分用に制限する例です。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
意味はこうです。
users/{userId}
↓
本人だけ読み書きOK
それ以外
↓
ログインしていれば読み書きOK
最初はこのくらいで十分です。
Step 12:teamsのルールは少し難しい
チームアプリでは、次の条件が必要になります。
チームメンバーだけチームを見られる
owner/adminだけメンバー追加できる
ownerだけ権限変更できる
owner/adminだけタスク削除できる
viewerは見るだけ
これは一気に書くと難しいです。
このページでは、まず考え方だけ押さえます。
Flutter側でrole確認
Firestore Rules側でもrole確認
次のページ以降で、少しずつ作ります。
Step 13:Security Rulesで使う主な言葉
| 書き方 | 意味 |
|---|---|
request.auth | ログイン情報 |
request.auth.uid | ログイン中ユーザーのuid |
resource.data | すでに保存されているデータ |
request.resource.data | これから保存しようとしているデータ |
get() | 他のドキュメントを読んで確認する |
exists() | ドキュメントが存在するか確認する |
最初に覚えるのは、この2つだけでOKです。
request.auth != null
request.auth.uid
Step 14:Flutter側とRules側の役割
同じ権限制御でも、役割が違います。
| 場所 | 役割 |
|---|---|
| Flutter側 | ボタンを隠す。分かりやすく操作制御する |
| Firestore Rules側 | 本当に読み書きを許可・拒否する |
例です。
Flutter側
↓
viewerには削除ボタンを見せない
Firestore Rules側
↓
viewerが削除しようとしても拒否する
この2つを両方入れるのが大事です。
Step 15:permission-deniedは悪いエラーではない
Rulesが正しく効くと、権限がない操作は拒否されます。
そのときに出るのが、次のエラーです。
permission-denied
これは、必ずしも悪いエラーではありません。
権限がない人を止められた
↓
ルールが働いた
ただし、許可したい操作まで止まっている場合は、Rulesを見直します。
Step 16:確認用チェック
Firebase ConsoleでRulesを書いたあと、次を確認します。
ログイン中
↓
チーム一覧が表示される
ログアウト後
↓
Firestoreデータが読めない
新規登録後
↓
users/{uid} が作成される
チーム作成後
↓
teams/{teamId} が作成される
まずは、ログイン中だけ動くことを確認します。
よくあるエラーと直し方
| エラー | 原因 | 直し方 |
|---|---|---|
permission-denied | Rulesで拒否されている | ログイン状態とRulesを確認 |
| ログインしているのに読めない | request.auth != null の条件に合っていない | Authenticationでログインできているか確認 |
| users作成で失敗する | usersルールが本人以外を拒否している | request.auth.uid == userId を確認 |
| ルールを書いたのに反映されない | 公開していない | Publish / 公開 を押す |
| ルールの構文エラー | {} や ; が足りない | コピペし直す |
| 急に全部動かなくなった | ルールが厳しすぎる | まずログイン必須ルールに戻して確認 |
開発用に戻したい場合
うまく動かなくなって学習が止まる場合は、一時的に開発用ルールに戻して確認してもOKです。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
ただし、これは学習中だけです。
本番公開では使いません。
入門用おすすめルール
この章の最初は、次のルールがおすすめです。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
理由はシンプルです。
ログインしている人だけOK
未ログインはNG
まずはここから始めます。
次に目指すルール
次の段階では、このように分けていきます。
users
↓
本人だけ読み書きOK
teams
↓
チームメンバーだけ読み取りOK
members
↓
owner/adminだけ追加OK
ownerだけ権限変更OK
tasks
↓
メンバーだけ読み取りOK
viewer以外は作成・編集OK
owner/adminだけ削除OK
一気にやると難しいので、次のページから少しずつ進めます。
最短作業まとめ
読むのが大変な人は、ここだけ見てください。
1. Firebase Consoleを開く
https://console.firebase.google.com/
2. Firestore Rulesを開く
Build
↓
Firestore Database
↓
Rules
3. 入門ルールを貼る
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
4. 公開する
Publish / 公開
5. アプリで確認する
flutter run
チェックリスト
□ Firebase Consoleを開いた
□ 今回のプロジェクトを選んだ
□ Firestore Databaseを開いた
□ Rules画面を開いた
□ 開発用ルールが危険だと理解した
□ request.auth != null の意味を理解した
□ ログイン必須ルールを書いた
□ Publish / 公開 を押した
□ ログイン中にアプリが動くことを確認した
□ 未ログインではFirestoreを読めないと理解した
□ Flutter側とRules側の役割の違いを理解した
ミニ確認問題
Q1. Firestore Security Rulesは何のためにありますか?
回答
Firestoreのデータを守るためです。
誰が読めるか、誰が書けるかを決めます。
Q2. request.auth != null は何を意味しますか?
回答
ログインしている人だけ許可する、という意味です。
Q3. Flutter側でボタンを隠せば、Rulesは不要ですか?
回答
不要ではありません。
Flutter側は画面の制御です。
Firestore Rules側で、本当にデータを守る必要があります。
Q4. 開発用の allow read, write: if true; は本番で使えますか?
回答
使えません。
誰でも読み書きできる危険なルールです。
Q5. このページでnpmや環境変数は必要ですか?
回答
必要ありません。
Firebase ConsoleでRulesを変更するだけです。
このページのまとめ
- Flutter側の制御だけでは、本番アプリとして不十分。
- Firestore Security Rulesでデータそのものを守る。
- 開発用の
allow read, write: if true;は本番では危険。 - 最初は
request.auth != nullでログイン必須にする。 request.auth.uidはログイン中ユーザーのuid。permission-deniedは、Rulesが効いているサインでもある。- Flutter側とFirestore Rules側の両方で権限制御する。
- このページではnpmや環境変数は不要。
次のページでやること
次のページでは、users/{uid} のSecurity Rulesを作ります。
本人だけが自分のプロフィールを読み書きできるようにします。
