概要
- ReactみたいなSPAからFirestoreに改竄されたくない情報を書き込む
- クライアント側で書き込むと想定外の部分までユーザが改竄できるため、それを防ぐ
ex. userドキュメントのプロフィールだけを更新したはずが、悪意のあるユーザがUIDフィールドを改竄対象のUIDにしたリクエストをFirestoreに送信することで他人のプロフィールを改竄できる
1. Firebase Functionsで書き込む
Firebase FunctionsではFirebase Authenticationのトークンを検証できるので便利
.region("asia-northeast1") // region指定
.https.onCall(async (data, context) => {
if (!context.auth) {
throw new functions.https.HttpsError(
"failed-precondition",
"The function must be called " + "while authenticated."
);
}
// 話が逸れるがdataをこういう感じでバリデーションすることもできる
if (!(typeof text === "string") || text.length === 0) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError(
"invalid-argument",
"The function must be called with " +
'one arguments "text" containing the message text to add.'
);
}
return;
});
2. セキュリティルールでバリデーションする
ただし、様々なバリデーションチェックを実装する必要があり、事故りやすい.
以下の記事を参考にすると良かった
Cloud Firestoreで「いいね」機能を実装するときの勘所 – su- tech blog
注意点
・readとwriteのメソッドは以下の細かなメソッドも含むものなので安易にtrueにしない(writeをtrueにするとユーザはドキュメントを削除できる権限を持つことになる
read: get,list
write: create,update,delete
・updateは要注意。他人のデータを改竄できるようになってないかを確認する
ex. uidフィールドをupdateできてしまう
対策:
- update前後で変更されてはいけないデータをバリデーションする
- hasOnlyでupdateできるフィールドを制限する
・セキュリティルールはVScodeとかで書いた方が楽。formatterのプラグインはあるがぶっ壊れている模様。
以下は代表的な関数とか
//create時のチェック
function validateUid() {
return incomingData().Uid == request.auth.uid;
}
//update時のチェック
function validateUpdate(giftId){
return request.resource.data.Uid == request.auth.uid;
}
3. フィールドそのもの変更をセキュリティルールで禁止する
特定のフィールドへのアクセスを制御する | Firebase Documentation