I'm working on setting up Firestore security rules, but I'm facing an issue where my custom function getUserOrganization() doesn't seem to return the correct value when used in matching conditions. Specifically, the function is supposed to return the organization ID of the authenticated user, but the matching condition doesn't seem to work as expected.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /Users/{userId} {
allow read, write: if request.auth.uid == userId;
}
match /Organisations/{orgId} {
allow read, write: if request.auth != null && getUserOrganization() == orgId;
match /{subcollection=**}/{docId} {
allow read, write: if request.auth != null && getUserOrganization() == orgId;
}
}
}
// Function to get the user's organization from their document
function getUserOrganization() {
return get(/databases/$(database)/documents/Users/$(request.auth.uid)).data.organisation.id;
}
}
Issue
When I try to access an organization document using the rule:
allow read, write: if request.auth != null && getUserOrganization() == orgId;
It throws a permission error. However, if I hardcode the organization ID like this:
allow read, write: if request.auth != null && "Sjc7mG12B0LPPe5bcJOf" == orgId;
The rule works as expected, and access is granted.
This leads me to believe that the getUserOrganization() function might not be returning the correct value or might be returning a value in a different format (e.g., different data type, string encoding, etc.).
What I've Tried:
getUserOrganization()
function is correctly fetching the organization ID from the user's document.Additional Information:
Any insights or suggestions on how to fix this issue would be greatly appreciated.
From what I understand or from my past experience with Firebase security rules, I think they shouldn't return anything other than boolean
values.
So, can you try doing this instead:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /Users/{userId} {
allow read, write: if request.auth.uid == userId;
}
match /Organisations/{orgId} {
allow read, write: if request.auth != null && getUserOrganization(orgId);
match /{subcollection=**}/{docId} {
allow read, write: if request.auth != null && getUserOrganization(orgId);
}
}
}
// Function to get the user's organization from their document
function getUserOrganization(orgId) {
return get(/databases/$(database)/documents/Users/$(request.auth.uid)).data.organisation.id == orgId;
}
}
In this, you're directly passing the orgId
as an argument, comparing it inside the function and returning the resulting boolean.
Let me know if that works :)