![見出し画像](https://assets.st-note.com/production/uploads/images/100326054/rectangle_large_type_2_b291bc162d2d9e495508808a77e6a9ec.png?width=1200)
Firebaseセキュリティルール
「Firebase」の「Firebaseセキュリティルール」についてまとめました。
1. Firebaseセキュリティルール
「Firebase」では、「Firebase セキュリティルール」を使用して、「Cloud Firestore」「Cloud Storage」のデータを保護します。ユーザーがアクセスできるデータを定義します。
2. 本番モードとテストモード
「Cloud Firestore」「Cloud Storage」ではストレージ構築時にセキュリティルールとして、「本番モード」と「テストモード」の選択を要求されます。
「本番モード」は全ユーザーアクセス不可、「テストモード」は全ユーザーアクセス可となります。
・本番モード - 全ユーザーアクセス不可
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
・テストモード - 全ユーザーアクセス可 (1ヶ月間)
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.time < timestamp.date(2023, 4, 1);
}
}
}
「Firebase Authentication」で認証したユーザーのみアクセス可にするには、次のように設定します。
・Firebase Authenticationで認証したユーザーのみアクセス可
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
本番運用では、データごとに自分のデータにしかアクセスできないようにするなど、サービスに適したルールを設定する必要があります。
3. Firebaseセキュリティルールの書式
3-1. 基本書式
「セキュリティルール言語」の基本書式は、次のとおりです。
rules_version = '2';
service <<name>> {
// リソースパスのマッチング
match <<path>> {
// 条件がtrueの場合に要求を許可
allow <<methods>> : if <<condition>>
}
}
・rules_version : 構文のバージョン (v2)
・service : ルールが適用されるサービス (firebase.storage, cloud.firestore)
・match : ルールが適用されるストレージのパス
・allow : trueと評価された場合に要求を許可
・methods : メソッド (get, list, create, update, delete)
・condition : コンディション
3-2. match
「match」には、次の2種類があります。
・Partial matches : request.pathのプレフィックス一致
・Complete matches : request.pathの全体一致
「request.path」に「/example/hello/nested/path」を渡すと、次のように許可するかどうかを判定します。{variable} はシングルセグメントワイルドカード、{variable=**} はマルチセグメントワイルドカードとなります。
service firebase.storage {
// Partial match
match /example/{singleSegment} { // singleSegment == 'hello'
allow write; // writeを不許可
// Complete match.
match /nested/path { // singleSegment visible in scope.
allow read; // readを許可
}
}
// Complete match
match /example/{multiSegment=**} { // multiSegment == /hello/nested/path
allow read; // readを許可
}
}
3-3. allow
「allow」で許可するかどうかは、一致したすべてのルールの論理和になります。次の例では、2つ目のルールでread・deleteを許可していませんが、1つ目のルールでread・deleteを許可してるため、許可となります。
service firebase.storage {
// userディレクトリ下のデータのread・deleteを許可
match /users/{userId}/{anyUserFile=**} {
allow read, delete: if request.auth != null && request.auth.uid == userId;
}
// userディレクトリ下のpngのread・delete・writeを許可
match /users/{userId}/images/{imageId} {
allow write: if request.auth != null && request.auth.uid == userId && imageId.matches('*.png');
}
}
3-4. methods
「allow」に指定する「methods」は、次のとおりです。
・Convenience methods
・read
・write
・Standard methods
・get
・list
・update
・delete
同じmatch内でのreadやwriteのオーバーラップはエラーとなります。たとえば、次のルールはエラーとなります。
service bad.example {
match /rules/with/overlapping/methods {
// 認証済みユーザーのreadを許可
allow read: if request.auth != null;
match another/subpath {
// readのオーバーラップでエラー
allow get: if request.auth != null && request.auth.uid == "me";
// writeのオーバーラップでエラー
allow write: if request.auth != null;
allow create: if request.auth != null && request.auth.uid == "me";
}
}
}
3-5. function
セキュリティルールは、カスタム関数もサポートしています。JavaScriptに似ていますが、ドメイン固有の言語で記述されており、いくつかの重要な制限があります。
・関数には1つのreturnのみを含めることが可能。
ループや外部サービスの呼び出しはできません。
・関数は定義されているスコープの関数や変数にアクセス可能。
例えばcloud.firestoreで定義された関数は、リソース変数、get()、exists()などの組み込み関数にアクセスできます。
・関数は他の関数を呼び出すことは可能だが再帰は不可。
呼び出しスタックの深さは最大20です。
・letを使って変数を定義することが可能。
最大10個持つことができますが、returnで終了しなければなりません。
service cloud.firestore {
match /databases/{database}/documents {
// 認証済みユーザーか、データが「public」である場合はtrue
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}
let代入文は「;」で区切る必要があります。
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
let isAdmin = exists(/databases/$(database)/documents/admins/$(userId));
return isAuthor || isAdmin;
}
データアクセスには遅延が発生します。以下では、isAuthorがtrueの場合のみ2番目の関数を呼び出して対策しています。
function isAdmin(userId) {
return exists(/databases/$(database)/documents/admins/$(userId));
}
function isAuthorOrAdmin(userId, article) {
let isAuthor = article.author == userId;
return isAuthor || isAdmin(userId);
}
4. Firebaseセキュリティルールの変数
4-1. request
「request」は、データアクセスのリクエストの情報を、ルールで利用するための変数です。
・request.auth : Firebase Authentication からの認証資格情報を含むJSON Web トークン (JWT)
・request.method : メソッド
・request.params : request.resourceに関連しないデータ
・request.path : ターゲットリソースのパス
4-2. resource
「resource」は、データアクセスをリクエストされているデータの情報を、ルールで利用するための変数です。
キーと値のペアのマップで表されるサービス内の現在の値です。条件内でリソースを参照すると、サービスから値が最大 1 回読み取られます。このルックアップは、リソースのサービス関連のクォータにカウントされます。
4-3. auth
「auth」はデータアクセスをリクエストしているユーザーの情報を、ルールで利用するための変数です。
・auth.uid : ユーザーID
・auth.token : Authenticationによって収集された値のマップ
auth.tokenには、次の値が含まれます。
・email : メールアドレス
・email_verified : ユーザーにメールアドレスへのアクセス権があるかどうか
・phone_number : 電話番号
・name : ユーザーの表示名
・sub : Firebase UID (プロジェクト内で一意)
・firebase.identities : このユーザーのアカウントに関連付けられている IDの辞書 (email, phone, google.com, facebook.com, github.com, twitter.com)
・firebase.sign_in_provider : ログインプロバイダ (custom, password, phone, anonymous, google.com, facebook.com, github.com, twitter.com)
・firebase.tenant : tenantId
関連
この記事が気に入ったらサポートをしてみませんか?