1

As recommended in the firebase documentation, my users are all stored under a main Users node, with each child being a corresponding Firebase Auth user ID for lookup purposes. For example, here's what it looks like:

Users
   ABCDEF12345
     name: xxx
     age: xxx
     etc: xxx

How do I make it possible for all users to read the parent node ID (ABCDEF12345), but NOT the underlying data? I'm not able to get this to work with either $user_id or the $uid variables, as they by default provide access to all underlying data and override specific fields because of the cascading effect. I want it to be possible for users to be able to read the user ID so they can perform lookups, but for there to be additional security checks in place in order to access some underlying values (i.e. maybe name will be a public facing variable with no restrictions but age must be a auth.uid === $uid case).

I want to be able to do something like this:

{
  "rules": {
    "Users": {
      "$uid": {
      "firstName" {
       ".read": "some specific conditions here that don't get overridden by $uid access"
...

When I implement something along the above lines, I am able to access the underlying data (firstName) but not the ID itself, unless I do something like this:

"rules": {
    "Users": {
      "$uid": {
       ".read": "true"

But this then gives access to everything below ID, which I don't want. I'm struggling to get this to work and the supporting documentation doesn't seem to help, despite them recommending the use of storing your users under an ID like this. Any help would be appreciated.

Thanks!

  • The RTDB has cascading permissions - it is not possible to grant access at a higher level but retract it at a deeper level because the RTDB can be thought of as a giant JSON file. The way to achieve what you want is to build a shallow index. You could set it up with the user IDs as the keys and the value as `1` or `true`. You can also do username searches as described in [this answer](https://stackoverflow.com/a/67246437/3068190) (while that OP is using Firestore, the username lookup stuff is all RTDB). Alternatively, split your user data into `publicUser` and `privateUser` with proper rules. – samthecodingman Aug 31 '22 at 03:00
  • Thank you so much for your response. Just to check my understanding - with the shallow index, do you mean store another field inside the user with the same ID, and just specify that one to have free read access? So the parent node isn't being read, but an identical copy under that user is? – 8bitsymphony Aug 31 '22 at 03:41
  • The shallow index is a different tree in your database entirely (not nested under `/Users`) like shown in the linked answer where I created a separate `/usernames` tree, or like I described in my other comment where you create a mapping of user IDs to a value of `true` or `1` (like Frank expanded upon in his answer below with the `/UserKeys` tree). – samthecodingman Aug 31 '22 at 07:21

1 Answers1

0

As Sam commented: permissions in Realtime Database security rules cascade downwards. Once you've given permission to a user at a certain level in the JSON tree, you cannot take that permission away anymore on a lower level.

The common workaround is to create an additional, second data structure that has only the keys that you want to share. So something like:

Users
   ABCDEF12345
     name: xxx
     age: xxx
     etc: xxx
UserKeys
    ABCDEF12345: true

The UserKeys node here only has the keys you want to share, and a true value for each key as you can't have a path without a value in the database. Now you can grant full read access to UserKeys to only share the keys, and then implement tighter access control on the Users node.

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807