自分の書いたFirebaseのsecurity ruleが本当に安全か知りたい、アドバイスをいただきたい

実現したいこと

自己開発のマッチングアプリの開発にfirebaseを使っています。リリースするにあたり、セキュリティが本当に安全かどうかを調べたいです。

発生している問題・分からないこと

自己流で書いてみたのですが、いまいち自分のコードの安全性に自信が持てません。アドバイスなど頂けたらありがたいです。Security ruleと主にfirebaseの情報に変更が起こるところのソースコードを載せておきます。他に必要なソースコードがございましたら教えて頂けたらありがたいです。

該当のソースコード

Security

1rules_version = '2'; 2service cloud.firestore { 3 match /databases/{database}/documents { 4 5 // 切り出した関数の記述 6 function isAuthenticated() { // 条件 1 7 return request.auth != null; 8 } 9 10 function isUserAuthenticated(userId) { // 条件 1 かつ 条件 2 11 return isAuthenticated() && userId == request.auth.uid; 12 } 13 14 // function isAdmin() { 15 // return isAuthenticated() && request.auth.token.admin == true; // Assuming 'admin' is a custom claim you've set 16 // } 17 18 // ユーザーデータのスキーマ検証 19 function isValidUser(user) { 20 return user.size() == 3 21 && 'createdAt' in user && user.createdAt is timestamp 22 && 'email' in user && user.email is string 23 && 'userId' in user && user.userId is string; 24 } 25 26 27 function isValidUserFS(user) { 28 return user.size() == 12 29 && 'bio' in user && user.bio is string 30 && 'cur_matching' in user && user.cur_matching is string 31 && 'done' in user && user.done is bool 32 && 'facebook' in user && user.facebook is string 33 && 'imageLink' in user && user.imageLink is string 34 && 'instagram' in user && user.instagram is string 35 && 'matchings' in user && user.matchings is list 36 && 'phone' in user && user.phone is string 37 && 'preference' in user && user.preference is string 38 && 'sex' in user && user.sex is string 39 && 'username' in user && user.username is string 40 && 'wait' in user && user.wait is bool; 41 } 42 43 // ルールの記述 44 match /users/{userId} { 45 46 // ユーザー情報の取得のルール 47 allow get: if isUserAuthenticated(userId); 48 49 // ユーザー情報の作成のルール 50 allow create: if isUserAuthenticated(userId) 51 // スキーマ検証 52 && isValidUser(request.resource.data) 53 // データのバリデーション 54 && request.resource.data.createdAt == request.time 55 && request.resource.data.userId == userId; 56 57 } 58 59 match /Users/{email} { 60 allow read: if isAuthenticated(); 61 62 allow create: if isAuthenticated() && isValidUserFS(request.resource.data); 63 64 allow update: if isAuthenticated() && isValidUserFS(request.resource.data); 65 } 66 67 match /Female_match_stack/Counter { 68 // Rules for 'Counter' document 69 allow read, update: if isAuthenticated(); 70 } 71 72 match /Female_match_stack/{document=**} { 73 allow read: if isAuthenticated(); // Only authenticated users can read 74 75 // Allow updating only the stack array, and only allow adding the user's own email 76 allow update: if request.auth != null && 77 request.resource.data.stack.size() == resource.data.stack.size() + 1 && 78 request.resource.data.stack[request.resource.data.stack.size() - 1] == request.auth.token.email; 79 80 allow create: if isAuthenticated(); 81 } 82 83 match /Male_match_stack/Counter { 84 // Rules for 'Counter' document 85 allow read, update: if isAuthenticated(); 86 } 87 88 match /Male_match_stack/{document=**} { 89 // Rules for all documents under Male_match_stack other than 'Counter' 90 allow read: if isAuthenticated(); // Only authenticated users can read 91 92 // Allow updates only if adding to 'stack' with the user's own email 93 allow update: if request.auth != null && 94 request.resource.data.stack.size() == resource.data.stack.size() + 1 && 95 request.resource.data.stack[request.resource.data.stack.size() - 1] == request.auth.token.email; 96 97 allow create: if isAuthenticated(); 98 } 99 } 100}

Flutter

1Future<void> editCondition() async { 2 User? currentUser = _auth.currentUser; 3 if (currentUser == null || currentUser.email == null) { 4 return; 5 } 6 DocumentSnapshot userDoc = await _firestore.collection('Users').doc(currentUser.email).get(); 7 DocumentSnapshot counterDoc = await _firestore.collection('Male_match_stack').doc('Counter').get(); 8 9 String gender = userDoc['sex']; 10 String collectionName = gender == 'male' ? 'Male_match_stack' : 'Female_match_stack'; 11 12 await _firestore.collection(collectionName).doc(counterDoc['num'].toString()).update({ 13 'stack': FieldValue.arrayUnion([currentUser.email]) 14 }); 15 await _firestore.collection('Users').doc(currentUser.email).update({'wait': true}); 16 } 17 18 Future<void> makeMatch() async{ 19 CollectionReference counts = FirebaseFirestore.instance.collection('Male_match_stack'); 20 final counter = await counts.doc('Counter').get(); 21 final cur_cnt = counter.get('num'); 22 CollectionReference males = FirebaseFirestore.instance.collection('Male_match_stack'); 23 final male = await males.doc(cur_cnt.toString()).get(); 24 final maleStack = male.get('stack'); 25 int maleLeng = maleStack.length; 26 CollectionReference females = FirebaseFirestore.instance.collection('Female_match_stack'); 27 final female = await females.doc(cur_cnt.toString()).get(); 28 final femaleStack = female.get('stack'); 29 int femaleLeng = femaleStack.length; 30 final new_cnt = cur_cnt + 1; 31 FirebaseFirestore.instance.collection('Male_match_stack').doc('Counter').update({ 32 'num': new_cnt 33 }); 34 FirebaseFirestore.instance.collection('Female_match_stack').doc('Counter').update({ 35 'num': new_cnt 36 }); 37 if (maleLeng.isOdd){ 38 maleLeng -= 1; 39 FirebaseFirestore.instance.collection('Male_match_stack').doc(new_cnt.toString()).set({ 40 'stack': [maleStack.last] 41 }); 42 } else { 43 FirebaseFirestore.instance.collection('Male_match_stack').doc(new_cnt.toString()).set({ 44 'stack': [] 45 }); 46 } 47 if (femaleLeng.isOdd){ 48 femaleLeng -= 1; 49 FirebaseFirestore.instance.collection('Female_match_stack').doc(new_cnt.toString()).set({ 50 'stack': [femaleStack.last] 51 }); 52 } else { 53 FirebaseFirestore.instance.collection('Female_match_stack').doc(new_cnt.toString()).set({ 54 'stack': [] 55 }); 56 } 57 if (maleLeng>1){ 58 for (int i = 0; i<(maleLeng/2); i++){ 59 FirebaseFirestore.instance.collection('Users').doc(maleStack.elementAt(i)).update({ 60 'cur_matching': maleStack.elementAt(maleLeng-1-i), 61 'matchings': FieldValue.arrayUnion([maleStack.elementAt(maleLeng-1-i)]), 62 'wait': false, 63 'done': false 64 }); 65 FirebaseFirestore.instance.collection('Users').doc(maleStack.elementAt(maleLeng-1-i)).update({ 66 'cur_matching': maleStack.elementAt(i), 67 'matchings': FieldValue.arrayUnion([maleStack.elementAt(i)]), 68 'wait': false, 69 'done': false 70 }); 71 } 72 } 73 if (femaleLeng>1){ 74 for (int i = 0; i<(femaleLeng/2); i++){ 75 FirebaseFirestore.instance.collection('Users').doc(femaleStack.elementAt(i)).update({ 76 'cur_matching': femaleStack.elementAt(femaleLeng-1-i), 77 'matchings': FieldValue.arrayUnion([femaleStack.elementAt(femaleLeng-1-i)]), 78 'wait': false, 79 'done': false 80 }); 81 FirebaseFirestore.instance.collection('Users').doc(femaleStack.elementAt(femaleLeng-1-i)).update({ 82 'cur_matching': femaleStack.elementAt(i), 83 'matchings': FieldValue.arrayUnion([femaleStack.elementAt(i)]), 84 'wait': false, 85 'done': false 86 }); 87 } 88 } 89 }

試したこと・調べたこと

上記の詳細・結果

何個かsecurity ruleの書き方テンプレートなどをググってみた。

補足

特になし

コメントを投稿

0 コメント