I have a database where the rules are simple, users can only write to their own individual child nodes. But I also wanted the moderators that I listed in a child node/property to be able to access the users data.
How do I write the rules so that the listed admin uids (admin1, admin2, admin3) can access all user nodes?
The only solution I could come up with is only this, but it is not very convenient since its gonna be a long condition.
{
"rules": {
"users": {
"$uid": {
".write": "$uid === auth.uid || auth.uid === 'admin1' || auth.uid === 'admin2' || auth.uid === 'admin 3'"
}
}
}
}
I thought I could reference the "uid" values under the admin node using the $ variable, but turns out that's not how the security rule works.
{
"rules": {
"admins":{
"uid" : "$adminUIDs"
}
"users": {
"$uid": {
".write": "$uid === auth.uid || auth.uid.contains($adminUIDs)"
}
}
}
}
The way that I would approach this is to utilize custom auth tokens that contain a custom claim for the user role.
That custom claim will then be available for your Firebase RTDB rules for more extensible authorization.
For example, after a user has successfully authenticated client-side, their auth token would be passed to the backend to generate a custom token:
const claims = {
admin: true,
someOtherClaim: "foobar"
};
getAuth()
.createCustomToken(userId, claims)
.then((customToken) => {
// Send token back to client
})
.catch((error) => {
console.log('Error creating custom token:', error);
});
Afterwards in your RTDB rules, you can have much simpler logic to determine who has access to a particular record:
{
"rules": {
"users": {
"$uid": {
".write": "$uid === auth.uid || auth.token.admin === true || auth.token.someOtherClaim === 'foobar'"
}
}
}
}