Securely query data

This page builds on the concepts inStructuring Security Rules andWriting Conditions for Security Rules to explain howCloud Firestore Security Rules interact with queries. It takes a closer look at howsecurity rules affect the queries you can write and describes how to ensure yourqueries use the same constraints as your security rules. This page alsodescribes how to write security rules to allow or deny queries based on queryproperties likelimit andorderBy.

Note: The server client libraries bypass allCloud Firestore Security Rules and instead authenticate throughGoogle Application Default Credentials. If you're using the server client libraries or the REST or RPC APIs, make sure to set upIdentity and Access Management (IAM) forCloud Firestore.

Rules are not filters

When writing queries to retrieve documents, keep in mind that security rules arenot filters—queries are all or nothing. To save you time and resources,Cloud Firestore evaluates a query against its potential result setinstead of the actual field values for all of your documents. If a query couldpotentially return documents that the client does not have permission to read,the entire request fails.

Note: This behavior applies to queries that retrieve one or more documents froma collection and not to individual document retrievals. When you use adocument ID to retrieve a single document,Cloud Firestore readsthe document and evaluates the request using your security rules and the actualdocument properties.

Queries and security rules

As the examples below demonstrate, you must write your queries to fit theconstraints of your security rules.

Note: The same rules apply to both normal queries that return documents andaggregation queries. In other words,security rules control what conditions are allowed, not how data is returned.

Secure and query documents based onauth.uid

The following example demonstrates how to write a query to retrieve documentsprotected by a security rule. Consider a database that contains a collection ofstory documents:

/stories/{storyid}

{  title: "A Great Story",  content: "Once upon a time...",  author: "some_auth_id",  published: false}

In addition to thetitle andcontent fields, each document stores theauthor andpublished fields to use for access control. These examples assumethe app usesFirebase Authentication to set theauthor fieldto the UID of the user who created the document. FirebaseAuthentication also populates therequest.auth variable inthe security rules.

The following security rule uses therequest.auth andresource.data variables to restrict read and write access for eachstory to its author:

servicecloud.firestore{match/databases/{database}/documents{match/stories/{storyid}{//Onlytheauthenticateduserwhoauthoredthedocumentcanreadorwriteallowread,write:ifrequest.auth!=null &&request.auth.uid==resource.data.author;}}}

Suppose that your app includes a page that shows the user a list ofstorydocuments that they authored. You might expect that you could use the followingquery to populate this page. However, this query will fail, because it does notinclude the same constraints as your security rules:

Invalid: Query constraints do not matchsecurity rules constraints

// This query will faildb.collection("stories").get()

The query failseven if the current user actually is the author of everystory document. The reason for this behavior is that whenCloud Firestore applies your security rules, it evaluates the queryagainst itspotential result set, not against theactual properties ofdocuments in your database. If a query couldpotentially include documentsthat violate your security rules, the query will fail.

In contrast, the following query succeeds, because it includes the sameconstraint on theauthor field as the security rules:

Valid: Query constraints match securityrules constraints

varuser=firebase.auth().currentUser;db.collection("stories").where("author","==",user.uid).get()

Secure and query documents based on a field

To further demonstrate the interaction between queries and rules, the securityrules below expand read access for thestories collection to allow any user toreadstory documents where thepublished field is set totrue.

servicecloud.firestore{match/databases/{database}/documents{match/stories/{storyid}{//Anyonecanreadapublishedstory;onlystoryauthorscanreadunpublishedstoriesallowread:ifresource.data.published==true||(request.auth!=null &&request.auth.uid==resource.data.author);//Onlystoryauthorscanwriteallowwrite:ifrequest.auth!=null &&request.auth.uid==resource.data.author;}}}

The query for published pages must include the same constraints as the securityrules:

db.collection("stories").where("published", "==", true).get()

The query constraint.where("published", "==", true) guarantees thatresource.data.published istrue for any result. Therefore, this querysatisfies the security rules and is allowed to read data.

OR queries

When evaluating a logicalOR query (or,in, orarray-contains-any)against a ruleset,Cloud Firestore evaluates each comparison valueseparately. Each comparison value must meet the security rule constraints. Forexample, for thefollowing rule:

match/mydocuments/{doc}{allowread:ifresource.data.x >5;}

Invalid: Query does not guarantee thatx > 5 for all potential documents

// These queries will failquery(db.collection("mydocuments"),or(where("x","==",1),where("x","==",6)))query(db.collection("mydocuments"),where("x","in",[1,3,6,42,99]))

Valid: Query guarantees thatx > 5 for all potential documents

query(db.collection("mydocuments"),      or(where("x", "==", 6),         where("x", "==", 42)      )    )query(db.collection("mydocuments"),      where("x", "in", [6, 42, 99, 105, 200])    )

Evaluating constraints on queries

Your security rules can also accept or deny queries based on their constraints.Therequest.query variable contains thelimit,offset,andorderBy properties of a query. For example, your security rulescan deny any query that doesn't limit the maximum number of documentsretrieved to a certain range:

allowlist:ifrequest.query.limit<=10;
Note:You can breakread rules intoget andlistrules. Rules forget apply to requests for singledocuments, and rules forlist apply to queries and requests for collections.

The following ruleset demonstrates how to write security rules that evaluateconstraints placed on queries. This example expands the previousstoriesruleset with the following changes:

  • The ruleset separates the read rule into rules forget andlist.
  • Theget rule restricts retrieval of single documents to public documents ordocuments the user authored.
  • Thelist rule applies the same restrictions asget but for queries. Italso checks the query limit, then denies any query without a limit or with alimit greater than 10.
  • The ruleset defines anauthorOrPublished() function to avoid codeduplication.
servicecloud.firestore{match/databases/{database}/documents{match/stories/{storyid}{//Returns`true`iftherequestedstoryis'published'//ortheuserauthoredthestoryfunctionauthorOrPublished(){returnresource.data.published==true||request.auth.uid==resource.data.author;}//Denyanyquerynotlimitedto10orfewerdocuments//Anyonecanquerypublishedstories//Authorscanquerytheirunpublishedstoriesallowlist:ifrequest.query.limit<=10&&authorOrPublished();//Anyonecanretrieveapublishedstory//Onlyastory's author can retrieve an unpublished story      allow get: if authorOrPublished();      // Only a story'sauthorcanwritetoastoryallowwrite:ifrequest.auth.uid==resource.data.author;}}}

Collection group queries and security rules

By default, queries are scoped to a single collection and they retrieve resultsonly from that collection. Withcollection group queries, you canretrieve results from a collection group consisting of all collections with thesame ID. This section describes how to secure your collection group queriesusing security rules.

Secure and query documents based on collection groups

In your security rules, you must explicitly allowcollection group queries by writing a rule for the collection group:

  1. Make surerules_version = '2'; is the first line of your ruleset. Collectiongroup queries require thenew recursive wildcard{name=**} behavior of securityrules version 2.
  2. Write a rule for your collection group usingmatch /{path=**}/[COLLECTION_ID]/{doc}.

For example, consider a forum organized intoforum documents containingposts subcollections:

/forums/{forumid}/posts/{postid}

{  author: "some_auth_id",  authorname: "some_username",  content: "I just read a great story.",}

In this application, we make posts editable by their owners and readable byauthenticated users:

servicecloud.firestore{match/databases/{database}/documents{match/forums/{forumid}/posts/{post}{//Onlyauthenticateduserscanreadallowread:ifrequest.auth!=null;//Onlythepostauthorcanwriteallowwrite:ifrequest.auth!=null &&request.auth.uid==resource.data.author;}}}

Any authenticated user can retrieve the posts of any single forum:

db.collection("forums/technology/posts").get()

But what if you want to show the current user their posts across all forums?You can use acollection group query to retrieveresults from allposts collections:

varuser=firebase.auth().currentUser;db.collectionGroup("posts").where("author","==",user.uid).get()
Note: This query requires an index on theposts collection for fieldauthorand with collection group scope. If you haven't enabled this index, the querywill return an error link you can follow to create the required index.

In your security rules, you must allow this query bywriting a read or list rule for theposts collection group:

rules_version='2';servicecloud.firestore{match/databases/{database}/documents{//Authenticateduserscanquerythepostscollectiongroup//Appliestocollectionqueries,collectiongroupqueries,and//singledocumentretrievalsmatch/{path=**}/posts/{post}{allowread:ifrequest.auth!=null;}match/forums/{forumid}/posts/{postid}{//Onlyapost'sauthorcanwritetoapostallowwrite:ifrequest.auth!=null &&request.auth.uid==resource.data.author;}}}

Note, however, that these rules will apply to all collections with IDposts,regardless of hierarchy. For example, these rules apply to all of the followingposts collections:

  • /posts/{postid}
  • /forums/{forumid}/posts/{postid}
  • /forums/{forumid}/subforum/{subforumid}/posts/{postid}

Secure collection group queries based on a field

Like single-collection queries, collection group queries must also meet theconstraints set by your security rules. For example, we can add apublishedfield to each forum post like we did in thestories example above:

/forums/{forumid}/posts/{postid}

{  author: "some_auth_id",  authorname: "some_username",  content: "I just read a great story.",  published: false}

We can then write rules for theposts collection group based on thepublished status and the postauthor:

rules_version='2';servicecloud.firestore{match/databases/{database}/documents{//Returns`true`iftherequestedpostis'published'//ortheuserauthoredthepostfunctionauthorOrPublished(){returnresource.data.published==true||request.auth.uid==resource.data.author;}match/{path=**}/posts/{post}{//Anyonecanquerypublishedposts//Authorscanquerytheirunpublishedpostsallowlist:ifauthorOrPublished();//Anyonecanretrieveapublishedpost//Authorscanretrieveanunpublishedpostallowget:ifauthorOrPublished();}match/forums/{forumid}/posts/{postid}{//Onlyapost's author can write to a post      allow write: if request.auth.uid == resource.data.author;    }  }}

With these rules, Web, Apple, and Android clients can make the following queries:

  • Anyone can retrieve published posts in a forum:

    db.collection("forums/technology/posts").where('published', '==', true).get()
  • Anyone can retrieve an author's published posts across all forums:

    db.collectionGroup("posts").where("author", "==", "some_auth_id").where('published', '==', true).get()
  • Authors can retrieve all their published and unpublished posts across allforums:

    varuser=firebase.auth().currentUser;db.collectionGroup("posts").where("author","==",user.uid).get()

Secure and query documents based on collection group and document path

In some cases, you might want to restrict collection group queries based ondocument path. To create these restrictions, you can use the same techniques forsecuring and querying documents based on a field.

Consider an application that keeps track of each user's transactionsamong several stock and cryptocurrency exchanges:

/users/{userid}/exchange/{exchangeid}/transactions/{transaction}

{  amount: 100,  exchange: 'some_exchange_name',  timestamp: April 1, 2019 at 12:00:00 PM UTC-7,  user: "some_auth_id",}

Notice theuser field. Even though we know which user owns atransactiondocument from the document's path, we duplicate this information in eachtransaction document because it allows us to do two things:

  • Write collection group queries that are restricted to documents that includea specific/users/{userid} in their document path. For example:

    varuser=firebase.auth().currentUser;//Returncurrentuser's last five transactions across all exchangesdb.collectionGroup("transactions").where("user","==",user).orderBy('timestamp').limit(5)
  • Enforce this restriction for all queries on thetransactions collectiongroup so one user cannot retrieve another user'stransaction documents.

We enforce this restriction in our security rules and include data validationfor theuser field:

rules_version='2';servicecloud.firestore{match/databases/{database}/documents{match/{path=**}/transactions/{transaction}{//Authenticateduserscanretrieveonlytheirowntransactionsallowread:ifresource.data.user==request.auth.uid;}match/users/{userid}/exchange/{exchangeid}/transactions/{transaction}{//Authenticateduserscanwritetotheirowntransactionssubcollections//Writesmustpopulatetheuserfieldwiththecorrectauthidallowwrite:ifuserid==request.auth.uid &&request.data.user==request.auth.uid}}}

Next steps

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-17 UTC.