Search code examples
javascriptfirebasegoogle-cloud-firestorefirebase-security

Firebase Cloud Firestore subcollection rule permission-denied


My web app fetch some documents via query with two constraints:

const readReviews = async (gsin: string) => {
    const res = [];

    const ref = collectionGroup( db, 'reviews' );
        const constraints = [
        where('gsin', '==', gsin),
        orderBy( 'timestamp', 'asc' ),
    ];

    const q = query( ref, ...constraints );
    const querySnapshot = await getDocs(q);

    querySnapshot.forEach( (doc) => {
        res.push( doc.data() );
    } );
  
    return res;
}

And my Firestore rule is

match /products/{gsin} {
    allow read;
    //..,
  
    match /reviews/{reviewId} {
        allow read;
        
        //...
    }
}

When I fetch data from the web app. it just display a 'permission-denied' error.

I tried to make another rule to focus on reviews subcollection: permission-denied

match /reviews/{reviewId} {
    allow read;
}

When I allow read to everyone it makes the fetch just right

match /{document=**} {
    allow read;
}

So I think it is a rule-focused issue.


Solution

  • As in step 2 of the documentation on securely querying documents in collection groups, you need a top-level rule of this format:

    match /{path=**}/[COLLECTION_ID]/{doc}
    

    This is needed because a collection group matches collections with the given name no matter where they exist in the database.

    So add a top-level rule like this:

    match /(path=**)/reviews/{reviewId} {
        allow read;
    }