majestiq
majestiq

Reputation: 565

firebase firestore subcollection access rules

I have a firestore with a collection called "children" and a subcollection called events. The children documents have an array called "caretakers" which contains the authids for users that should have access to this document. My question is, what is the right way to secure the subcollection. I am currently doing the following:

match /children/{childId} {
    allow read, write, delete, list: 
        if request.auth.uid in resource.data.caretakers;
    allow create:
        if true;
}

 match /children/{childId}/events/{eventId} {
    allow read,write,delete,get:
    if request.auth.uid in get(/databases/$(database)/documents/children/$(childId)).data.caretakers
  }

Something about that get(...) doesn't feel right to me. Is that necessary? Do I really need to specify rules separately for each subcollection? or if the parent document has permissions.. those permissions should cascade down to subcollections?

Upvotes: 1

Views: 1558

Answers (3)

majestiq
majestiq

Reputation: 565

I'm answering my own question to note what I ended up going with as a solution.

In my case, the number of Users that have access to each {childId} is very low. Therefore, I ended up storing custom claims in the Users Auth object. Basically stored an array of {childId} in the Users auth object instead of storing a bunch of userIds into the Child object.

This allows me to do a direct check to see if the {childId} exists in the users auth object and saves me extra reads of data.

Upvotes: 0

Frank van Puffelen
Frank van Puffelen

Reputation: 598688

With your current structure unfortunately you will indeed need to read the parent document to check against its caretakers role for each subdocument. What's even worse is that this makes queries impossible, as you can't read from the parent document when querying events.

The common workaround for this is to duplicate the caretakers into each events document, so that you can query for it there, and the rules can then secure that only that query is allowed.

Upvotes: 2

Dharmaraj
Dharmaraj

Reputation: 50830

Yes you need to explicitly define rules for sub-collections. You can nest the sub-collection's rule in that collection itself to structure it.

Security rules apply only at the matched path, so the access controls defined on the [children] collection do not apply to the [events] subcollection

service cloud.firestore {
  match /databases/{database}/documents {
    match /children/{childId} {
      allow read, write, delete, list: if request.auth.uid in resource.data.caretakers;
      allow create: if true;
      // These rule will apply for docs in children collection only

      // Explicitly define rules for the 'events' subcollection
      match /events/{eventId} {
          allow read,write,delete,get: if request.auth.uid in get(/databases/$(database)/documents/children/$(childId)).data.caretakers
          // This rule will apply for docs in events sub-collections only
      }
    }
  }
}

You can read more about this at: How security rules work?

Upvotes: 2

Related Questions