Search code examples
firebase-realtime-databasefirebase-authenticationfirebase-security

How to give access to a list of UID in security rule of firebase realtime database


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?

enter image description here

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)"
      }
    }
  }
}

Solution

  • 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'"
          }
        }
      }
    }