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?
This rule is indeed going to allow anyone to mark themselves as an Admin, defeating the whole purpose of your rules (don't do this):
allow read, write: if get(/users/$(request.auth.uid)).data.admin == true;
What you rather want to do is:
admin: true
claim, which you can then check in your rules with: allow read, write: if auth.token.admin === true;
allow read, write: if isAdmin();
and then function isAdmin(request) { return request.auth.uid == "KqEizsqUQ6XMkUgLUpNxFnzLm4F3" }
.