问题
I am using cloud Firestore database and I have 'users' collection on my root database and in it there are all the users documents (named as the uid) and inside it the data I collect. I wanted to allow users to only read/write to their own collections so I started my security rules with
service cloud.firestore {
match /databases/{database}/documents {
// Allow only authenticated content owners access
match /users/{userId}/{documents=**} {
allow read, write: if request.auth.uid == userId
}
}
}
then I realized that the users don't have permission to create their own main document (it created it as a 'ghost' document). I also want to add data to it such as display name and email, so I added
// Allow users to read/write their own main user object
match /users/{userId} {
allow read, write: if request.auth.uid == userId
}
all works well but now I want to allow admin users to read/write to all user's collections and documents.
firebase's documentations suggests adding a key-value to the user's document such as (admin:true)
, so editing my security rules like so should do the trick:
match /users/{userId}/{documents=**} {
allow read, write: if request.auth.uid == userId
allow read, write: if get(/users/$(request.auth.uid)).data.admin == true; //-security breach?
}
but doesn't it creates a security breach where a user can technically update his own document with (admin:true)
and gain admin privilege?
if so, i'm guessing my approach should be creating a separate admins
collection and add my admins there and then do something in the lines of
allow read, write: if get(/admins/$(request.auth.uid)) != null
? or is there something prettier I can use?
回答1:
This rule is indeed going to allow anyone to mark themselves as an Admin, defeating the whole purpose of your rules:
allow read, write: if get(/users/$(request.auth.uid)).data.admin == true;
What you'll want to do is:
- Either give the admin users a custom admin: true claim, which you can then check in your rules with:
allow read, write: if auth.token.admin === true;
- Keep an explicit list of UIDs for your admins in your security rules, and then check that in each rule. So:
allow read, write: if isAdmin();
and thenfunction isAdmin(request) { return request.auth.uid == "KqEizsqUQ6XMkUgLUpNxFnzLm4F3" }
. - Keep a list of admin UIDs in another (not normally writeable) collection in Firestore, and check against that. That's pretty much what you've described, and is the most common approach if you want to be add/remove admins quickly and easily.
回答2:
Just to clarify, if you're going to use get() you need to put the full path. So in your case, it will be:
allow read: if get(/databases/$(database)/documents/admins/$(request.auth.uid)).data.admin == true
You can read more about it here
来源:https://stackoverflow.com/questions/60179115/firebase-security-rule-to-allow-admin-users-to-read-write-all-other-users-create