I have a bunch of collections to define security rules for and they all have logical OR
operators in them to account for admin rights. Here is one such example:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isAdmin() {
return request.auth != null && get(/databases/$(database)/documents/userProfiles/$(request.auth.uid)).data.admin == true;
}
function isSignedIn() {
return request.auth != null;
}
function isOwnDocument() {
return request.auth.uid == request.resource.id
}
match /userSettings/{doc} {
allow read: if isOwnDocument() || isAdmin();
allow write: if isOwnDocument() || isAdmin();
}
}
}
Could I, instead, declare admin rights up front and omit the OR
operator?
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isAdmin() {
return request.auth != null && get(/databases/$(database)/documents/userProfiles/$(request.auth.uid)).data.admin == true;
}
function isSignedIn() {
return request.auth != null;
}
function isOwnDocument() {
return request.auth.uid == request.resource.id
}
match /{document=**} {
allow read: if isAdmin();
allow write: if isAdmin();
}
match /userSettings/{doc} {
allow read: if isOwnDocument();
allow write: if isOwnDocument();
}
}
}
Would this be a good practice?
CodePudding user response:
Could I, instead, declare admin rights up front and omit the OR operator?
Yes!
I just checked the Rules Playground in the Firebase Console.
To try the Rules Playground, go to the Rules tab of Cloud Firestore and click on Rules Playground. You will see it bottom left to the Rules Editor. There, you can build the data and an authenticated state and from there simulate a request.
Would this be a good practice?
Yes, certainly. It will make your Firestore Rules cleaner. So you won't need to be putting ||
(or) in every match.
Explanation
It's possible for a document to match more than one match statement. In the case where multiple allow expressions match a request, the access is allowed if any of the conditions is true
So when isAdmin()
is true (and because it is declared upfront for all documents), Firestore will allow access for the documents.
From the question comments ...
can you elaborate on what you mean by setting admin through custom claims?
Custom Claims is a feature in Firebase where you can assign different roles to users. You can use custom claims to set admin privileges, teacher permissions, or any role your app needs.
Custom Claims take valid JSON (preferably key-value pairs with boolean values).
Custom Claims on a user can be accessed in different parts of Firebase:
- In the clients, through
idToken
, - In the admin SDK, through
auth.token
, and - In the security rules (for Firestore, Realtime Database, and Storage).
So, in either of these parts of Firebase, you can check the custom claims on an authenticated user to give them access to resources or not.
Note that custom claims are not meant to be used as a store of data to extend the User object from Firebase Authentication. They are primarily there for security rules. Firebase will reject custom claims that are more than 1000 bytes.
Also, you can only manage custom claims on your projects in the admin SDK.
Learn about custom claims here.