Flutterアプリケーション開発概論

【Security Rules入門】画面側だけでなくFirestore側でデータを守る

44LINE風チームタスク管理アプリを作りながら、ログイン・データベース・権限管理を学ぶ
FlutteriOSAndroidMacOSWindows基礎から学ぶ開発アプリ開発

このページでやること

このページでは、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-deniedRulesで拒否されているログイン状態と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を作ります。

本人だけが自分のプロフィールを読み書きできるようにします。

教材トップへ戻る