Search code examples
firebasegoogle-cloud-firestoreangularfire2firebase-security

Firestore; security rule simulation passes but actually fails (uid as map key)


I can't understand why this Firestore security rule fails in web.

I'm using @angular/fire latest with a query on a collection and with firebase latest, but it works in simulation.

service cloud.firestore {
  match /databases/{database}/documents {
    // Match any document in the 'cities' collection
    match /events/{event} {
      allow read: if (resource.data.access.code == 'public' || (resource.data.access.code == 'protected' && resource.data.objname.objfield == "A"));
    }
  }
}

Here's the data:

enter image description here

If access.code is "protected", then we look at objname.objfield == "A". Checking access.code == "protected" lets me access the data, but the second part objname.objfield == "A" doesn't.

I don't understand why. I've made sure this property exists in all objects of the collection. (Firestore security rules based on map values)

I tried several different ways, they all pass in Simulation, because it's a single document query. An actual query at collection level does not go through permissions with the actual web call.

This is the query I'm making, which passes when there's no security rule in place

const pathAccessCode: firebase.firestore.FieldPath = new firebase.firestore.FieldPath('access', 'code');
const eventsUser: AngularFirestoreCollection<any> = this.firestore.collection('events', ref => ref.where(pathAccessCode, '==', 'protected'));
const eventsUser$: Observable<any> = eventsUser.valueChanges();
eventsUser$.subscribe(data => console.log(data) );

As you can see; some properties are recognised by the rule (access.code) but not others (objname.objfield).

The only think I can think of at this stage, is that access.code has been created before I started playing with the rules. objname.objfield however, was created after I started using rules.

Can this be a thing?

Thanks for your help


Solution

  • After asking Firebase support, I was told that in the context of queries, the security rules have to match the query themselves.

    That is; if I want to query documents with filters on fieldA and fieldB, then only fieldA & fieldB should be in the security rule.

    This is not what I want to achieve here however.

    Hope that helps anyone with the same issue.