Search code examples
firebasegoogle-cloud-firestorefirebase-security

Role based rule for Cloud Firestore access won't work


I'm trying to implement this rule into Firebase Firestore in order to access the data of the table "users" (which contains name and age of some people) if the role of the logged in user is "admin". Indeed I have two tables:

  • Roles (where every document has the same id as the registered users) with a field "role" that can be valued as "admin"
  • Users contains just names and ages, and should be accessed only by logged in admins.

This is the rule i wrote:

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
   match /users/{document} {
    allow read: if get(/databases/$(database)/documents/roles/$(request.auth.id)/role) == "admin"
    }
  }
}

In firebase console inside rule playground, by trying to do a get as an authenticated user which has the role "admin", by using the following path /users/RaafvyRPWYuN3IyqdoBa I get a red message saying "Simulated reading has been refused"

Image of the error

it is important to note that, inside /users/RaafvyRPWYuN3IyqdoBa the code is indeed the ID of one of the people that are listed in the table "users"

Here are the pictures about my database in Firestore.

Roles table People table

Can anyone help me to understand why the rule is not working as it should?


Solution

  • When you use get() in a rule, you must provide only the full path to the document to fetch. You can't use the path to reach into a field in the document. Once you have a document fetched, then you can reach into its fields using dot notation.

    Secondly, to use the uid of an authenticated user in a rule, use request.auth.uid (not "id").

    allow read: if get(/databases/$(database)/documents/roles/$(request.auth.uid)).data.role == "admin"
    

    I suggest familiarizing yourself with the documentation on accessing other documents for more details and examples on how this works.