セキュリティ ルールで安全に Firestore を使おう
この記事はユアマイスター アドベントカレンダー 2022の 8 日目の記事です。
はじめに
Firestoreはモバイルアプリケーションや Web アプリケーションのクライアントから直接アクセスすることができる NoSQL データベースです。そのため、データベースの接続先情報は公開されておりエンドユーザーが入手することができる情報になります。
悪意のあるユーザーがアクセスして好き勝手されないようにデータを守るための方法がセキュリティ ルールを書くことです。本記事ではデータを守るためのセキュリティ ルールの書き方を紹介します。
セキュリティ ルールを書く準備
アプリケーションのルートから firebase init firestore
を実行して必要なファイルを生成してください。
firestore-sample
├─── .firebaserc
├─── firebase.json
├─── firestore.indexes.json
└─── firestore.rules
firestore.rules
というファイルが生成されるので、ここにセキュリティ ルールを記入していきます。
例
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
データを守る
データを守るために読み取り時の認証・認可と書き込み時の認証・認可、スキーマ検証、バリデーションが考慮すべきポイントです。
認証・認可
Firebase SDK を利用して Firestore に接続すると Authentication と連動した認証を行うことができます。認証状態であれば、request の auth フィールドに認証ユーザーの情報が格納されます。
allow read: if request.auth != null;
また、ドキュメントパスの一部を Authentication の ID(uid)にすることで以下のようなルールを書くことができます。(もちろん、ドキュメントの ID のフィールドと比較することもできます)
match /users/{uid} {
allow read: if request.auth != null && request.auth.uid == uid;
}
スキーマ検証
Firestore は NoSQL でスキーマレスなデータベースではあるのですが、ユーザーに意図しないスキーマを設定されると不具合の原因になります。 不具合の発生を回避するために意図したキーのみがあるかの確認と値の型が正しいかの確認が必要です。
以下のドキュメントのスキーマを例に検証方法を紹介します。
// path: /user/{uid}
<uid>: {
displayName: '山田 太郎',
photo: {
url: 'https://www.sample.com/profile.jpg',
},
createdAt: 2022/12/01 12:34:56,
updatedAt: 2022/12/01 12:34:56,
}
各フィールドのキーの名前と値の型は以下のように検証します。
service cloud.firestore {
// スキーマを検証する関数
function isValid(user) {
return user.keys().toSet() == ['displayName', 'photo', 'createdAt', 'updatedAt'].toSet()
&& staff.displayName is string
&& user.photo.keys().toSet() == ['url'].toSet()
&& user.photo.url is string
&& user.createdAt is timestamp
&& user.updatedAt is timestamp;
}
match /users/{uid} {
// 自分のuserのみ作成できる
allow create: if request.auth != null
&& request.auth.uid == uid
&& isValid(request.resource.data);
}
}
バリデーション
スキーマ検証後、フィールドに対してバリデーションをかけることはよくあると思います。
例えば、displayName
が 1 文字以上であるという要件があるとします。以下のようにスキーマ検証後にバリデーションをかけます。
service cloud.firestore {
・
・
・
match /users/{uid} {
// 自分のuserのみ作成できる
allow create: if request.auth != null
&& request.auth.uid == uid
&& isValid(request.resource.data)
// displayNameは1文字以上であること
&& request.resource.data.displayName.size() >= 1;
}
}
さいごに
Firestore は手軽に使用できるデータベースである反面、セキュリティには十二分に気をつけてセキュリティルールを書いていく必要があります。 弊社テックリードの著書である実践 Firestoreは Firestore を使う前に読んでほしいおすすめの一冊です!
次回は Firebase Summit 2022 で発表があった新機能で記事を書こうかなっと思っています。また読んでもらえると嬉しいです!それでは!