Firestoreの「Missing or insufficient permissions」をRulesとQueryから切り分ける

Firestoreの権限エラーを、client SDKのSecurity RulesとAdmin SDKなどのIAM認可に分け、要求条件を確認する方法を解説します。

AIものさし編集部

Firestoreで「Missing or insufficient permissions」が出たとき、Security Rulesを全許可へ広げたり、認証設定を変えたりする前に、失敗した要求がどのAPI経路を通り、どのproject・database・document pathに対して、どの認証状態とqueryで実行されたかを分けてください。Web・Android・iOSなどのFirestore client SDKはSecurity Rulesで評価されます。一方、Admin SDKなどのserver client libraryはRulesを通らず、IAMで認可されます。最初の分岐を誤ると、Rulesを直しても症状が変わらないことがあります。

このエラーの原因は、少なくとも「request.authが想定と違う」「match pathが実際のdocument pathと一致しない」「queryがRulesの許可条件を保証しない」「実行先project/databaseや適用中のRulesが想定と違う」に分かれます。まず失敗した操作の記録を作り、該当する枝だけを確認します。この記事は一般的な診断手順です。特定のFirebase projectを調べたり、Rules変更を実行したりした結果ではありません。

まず失敗した要求を一行で記録する

ブラウザconsoleやアプリログから、失敗した操作を次の形に整理します。access token、refresh token、秘密鍵、ユーザーの個人情報は記録へ貼らないでください。uidやproject IDが必要なら、共有範囲を限定した記録にします。

表は横にスクロールできます

記録項目確認する値ここで分かること
SDK / APIWeb・Android・iOS client SDK、Admin SDK、REST/RPCなどRulesを調べるかIAMを調べるか
操作get、list/query、create、update、delete読み取り・一覧・書き込みのどの条件か
実行先Firebase project ID、database ID、emulatorか実環境か想定した設定を見ているか
パスcollection / document pathRulesのmatchと一致するか
認証状態未ログインか、ログイン済みか、想定uidかrequest.authの条件を満たすか
query条件where、orderBy、limitなどRulesが許可する結果集合を保証するか
適用中のRules実際にデプロイ済みのRulesと版ローカル編集内容と実行先が一致するか

「ユーザーはログインしている」といった画面上の状態だけでは十分ではありません。Firestoreへの要求時点で、そのSDK instanceが期待するFirebase projectへ接続され、期待するユーザーの認証状態を持っているかを確認します。ログイン成功後に別のFirebase app instanceを使っている、ログアウト直後の古い画面が残っている、認証listenerの初期化前にqueryを実行した、という可能性はアプリ側で確認してください。特定アプリでこれらが原因だとは断定できません。

Rulesを調べる前にclient SDKかserver SDKかを分ける

最初にFirestoreへの経路を特定します。

表は横にスクロールできます

経路主な認可の確認先よくある確認
Web / Android / iOSのFirestore client SDKCloud Firestore Security RulesとFirebase Authenticationrequest.auth、match path、Rules条件、query
Admin SDKなどserver client libraryGoogle Cloud IAM / service account実行principal、IAM role、project、credential
REST / RPCAPIの認証方式とIAMなど、その経路の公式認可条件client SDK Rulesが適用されると決めつけない

Cloud Firestoreの公式資料では、server client libraryはSecurity Rulesを迂回し、Google Application Default Credentials等で認証してIAMを使うと説明されています。そのため、サーバー側処理の失敗に対して、client用Rulesへ条件を足すのは原因と違う場合があります。どのSDKか確信が持てない場合は、依存パッケージ、初期化コード、実行環境、credentialの種類を確認してから調査先を決めます。credentialそのものをログへ出す必要はありません。

client SDKならrequest.authとRulesのmatchを照合する

client SDKの要求では、まず認証条件とpath条件を別々に見ます。Firebase Authenticationでユーザーが認証されていれば、Rules内のrequest.authにはその認証情報が渡されます。未認証状態ではrequest.authはnullです。ただし、認証済みであることだけでFirestoreのread/writeが許可されるわけではありません。Rulesのallow条件も満たす必要があります。

次に、コードが実際に参照するdocument pathとRulesのmatchを照合します。例えば、コードが /accounts//orders/ を読むなら、Rulesが /users//orders/ だけに適用される状態では一致しません。collection group queryを使う場合は、通常のcollection queryと同じpath想定でよいとは限らず、collection group向けのRules scopeを公式仕様に沿って確認します。pathの大文字小文字、collection名、database ID、ネスト階層も並べて確認してください。

読み取りも単一documentのgetとcollectionのlist/queryを分けてください。単一document readは特定のdocumentを対象にRules評価されます。queryは候補集合全体を対象にするため、単一document readが成功することだけではcollection queryの許可を証明しません。書き込みでは、作成前のresourceと作成後のrequest.resourceをどちらの条件に使っているか、更新対象のpathが同じかも確認します。

queryはRulesに許可された結果集合を保証する必要がある

Firestore Security Rulesは結果を後から絞り込むfilterではありません。queryが返し得るdocumentの中に、Rulesで拒否されるものが含まれる可能性があれば、実際のデータ上で拒否対象が見つからなくても、query全体が拒否されることがあります。queryの制約は、Rulesの条件が許す範囲を保証しなければなりません。

表は横にスクロールできます

Rulesの考え方query側で照合すること
所有者uidが一致するdocumentだけread可能queryにも同じuid条件があるか
publishedがtrueのdocumentを公開read可能queryでpublished == trueを保証しているか
listには最大件数が必要queryにRulesが認めるlimitがあるか
OR / in / array-contains-anyの各候補を条件で評価各候補値がすべてRules条件を満たすか
collection groupを許可する条件collection group queryのpathとRules version / matchが合うか

例えばRulesが「resource.data.ownerUid == request.auth.uid」のdocumentだけを許可するなら、collection全体を読むqueryでは他ユーザーのdocumentが結果に含まれる可能性を排除できません。ログイン中ユーザーの所有データだけを読むqueryへ制約を加える必要があります。この例は公式説明を簡略化した概念例で、特定のスキーマやコードに対する実装指示ではありません。field名やquery APIは実際のデータモデルに合わせてください。

まずRulesのread/list条件から必要なquery条件を抜き出し、次に実際のqueryを横に並べます。field名だけでなく、演算子、値、OR条件、limit、collection scopeを比較します。インデックス不足は通常別のエラーとして表れるため、このpermission errorを見ただけでインデックスを原因と決めつけず、実際のエラーとSDKログを確認します。

project・database・Rulesの反映先を確認する

アプリが意図したFirebase projectとFirestore databaseへ接続しているかを確認します。開発・staging・productionでFirebase configや環境変数が異なる場合、別projectに要求している可能性があります。複数databaseを使う構成ではdatabase IDも記録してください。emulator利用時には、SDKが実際にemulator hostへ接続しているか、予期せず実環境へ接続していないかも確認します。

次に、手元で編集しているRulesと、失敗が起きたprojectへ反映されているRulesを比べます。ローカルファイルが正しくても、デプロイ先や公開済みRulesが別なら実際の評価は変わりません。ConsoleまたはFirebase CLIで対象project、database、Rules内容、反映日時を確認します。Production Rulesの変更は利用者全体のアクセスに影響するので、原因未確定のまま全許可へ変更したり、広いmatchを足したりしないでください。

安全なRulesテストを組み立てる

本番データや本番Rulesを直接緩める前に、Firebase Local Emulator SuiteとSecurity Rules unit testingを使って、許可・拒否の両方を再現します。公式のRules unit testingライブラリは、未認証・認証済みcontextを分けたtestを作り、テスト用認証状態でRulesの挙動を確認する用途です。テストには、実際のRulesファイルが読み込まれていること、demo用または隔離されたproject IDを使っていること、Firestore emulatorへ接続していることを含めます。

表は横にスクロールできます

テスト期待する結果を決める前提
未認証client公開readを許すのか、認証を要求するのか
認証済み本人uid / role / document field条件を満たすか
別ユーザー他人のdocumentを拒否できるか
query条件ありRulesの条件が結果集合全体で成立するか
query条件なし拒否されるべき要求を拒否するか
書き込みcreate / update / deleteで必要なfieldやpathを確認するか

上表はテストケースを設計するためのチェックリストであり、現行projectに対する合否結果ではありません。EmulatorにRulesファイルを読み込まないと、公式資料の注意どおり初期状態でopen rulesとして扱われる可能性があります。テストが通ったことだけでProductionのRules反映まで確認済みとは言えません。テスト対象のRulesとproject設定が正しいことを確認し、結果と対象revisionを一緒に記録します。

調査結果から次の修正を選ぶ

原因が分かったら、変更対象を絞ります。

表は横にスクロールできます

確認結果次に行うこと避けること
request.authがnull / uidが違うclient初期化、ログイン状態、要求時点を確認全read/writeをpublicにする
document pathとmatchが違うコードのpathとRulesのmatchを修正対象として比較意味を確認せず広いwildcardを追加
queryがRulesの条件を保証しないRulesに合うquery条件か、データ設計を検討query結果の実データだけを見て通ると判断
server SDK / RESTのIAM経路実行principalと対象resourceのIAMを確認client Security Rulesだけを編集
project / database / emulatorが違うconfigと実際の接続先を照合本番設定を推測で差し替え
適用中Rulesが古い変更履歴とデプロイ対象を確認し、適用方法を計画原因が分かる前にProduction反映

本番Rulesを変える必要がある場合は、意図した利用者だけを許可する条件を保ち、最小差分で行います。アクセス範囲が広がる変更は、コードだけで自己判断せず、データの機密性と利用者への影響を確認してください。テストで「拒否されるべきケース」が通ってしまったなら、成功と数えず、ルールの緩和を戻して原因を調べます。

再発を減らす確認記録

permission-deniedを再発時に比較できるよう、次の情報を安全な範囲で残します。

  • Error全文からcredentialや個人情報を除いたもの

  • client SDK / server SDK / REST等の経路

  • 操作種別、collection/document path、projectとdatabase

  • request時点の認証状態と、Rulesで参照するuid / role

  • query条件一式とRulesの対応するallow条件

  • Emulatorまたは実環境の別、適用中Rulesの確認日時

  • allowされるケースとdenyされるケースのtest結果

  • 未確認の前提と、次に確認する担当・場所

原因が特定できなければ、広いアクセスを追加して先へ進めるのではなく、再現に必要な最小情報を揃えて管理者またはFirebase担当者へ渡します。Rulesの条件とqueryの関係を説明できる状態になってから修正を依頼してください。

まとめ:まずSDK経路と失敗したqueryを特定する

Web / Android / iOS client SDKなら、request.auth、document path、Rulesのallow条件、queryのpotential result、実際に適用されたRulesを順に照合します。Admin SDK等のserver経路ならIAMを調べます。実projectやRulesの内容が確認できない限り、原因を断定せず、全許可ルールも本番へ出しません。次は、失敗ログから操作種別・接続先・path・認証状態・query条件を記録し、該当する分岐をEmulatorで再現してください。

参考情報