Control access to specific fields

This page builds on the concepts inStructuring Security Rules andWriting Conditions for Security Rules to explain howyou can useCloud Firestore Security Rules to create rules that allow clients to performoperations on some fields in a document but not others.

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.

There may be times when you want to control changes to a document not atthe document level but at the field level.

For instance, you might want to allow a client to create or change a document,but not allow them to edit certain fields in that document. Or you may wish toenforce that any document that a client always creates contains a certain set offields. This guide covers how you can accomplish some of these tasks usingCloud Firestore Security Rules.

Allowing read access only for specific fields

Reads inCloud Firestore are performed at the document level. You eitherretrieve the full document, or you retrieve nothing. There is no way to retrievea partial document. It is impossible using security rules alone toprevent users from reading specific fields within a document.

If there are certain fields within a document that you want to keep hidden fromsome users, the best way would be to put them in a separate document. Forinstance, you might consider creating a document in aprivate subcollectionlike so:

/employees/{emp_id}

  name: "Alice Hamilton",  department: 461,  start_date: <timestamp>

/employees/{emp_id}/private/finances

    salary: 80000,    bonus_mult: 1.25,    perf_review: 4.2

Then you can add security rules that have different levels of access for thetwo collections. In this example, we're usingcustom auth claimsto say that only users with the custom auth claimrole equal toFinance canview an employee's financial information.

service cloud.firestore {  match /databases/{database}/documents {    // Allow any logged in user to view the public employee data    match /employees/{emp_id} {      allow read: if request.resource.auth != null      // Allow only users with the custom auth claim of "Finance" to view      // the employee's financial data      match /private/finances {        allow read: if request.resource.auth &&          request.resource.auth.token.role == 'Finance'      }    }  }}

Restricting fields on document creation

Cloud Firestore is schemaless, meaning that there are no restrictions atthe database level for what fields a document contains. While thisflexibility can make development easier, there will be times when you wantto ensure that clients can only create documents that contain specific fields,or don't contain other fields.

You can create these rules by examining thekeys method of therequest.resource.dataobject. This is a list of all fields that the clientis attempting to write in this new document. By combining this set of fieldswith functions likehasOnly()orhasAny(),you can add in logic that restricts the types of documents a user can add toCloud Firestore.

Requiring specific fields in new documents

Let's say you wanted to make sure that all documents created in arestaurantcollection contained at least aname,location, andcity field. You coulddo that by callinghasAll()on the list of keys in the new document.

servicecloud.firestore{match/databases/{database}/documents{//Allowtheusertocreateadocumentonlyifthatdocumentcontainsaname//location,andcityfieldmatch/restaurant/{restId}{allowcreate:ifrequest.resource.data.keys().hasAll(['name','location','city']);}}}

This allows restaurants to be created with other fields as well, but it ensuresthat all documents created by a client contain at least these three fields.

Forbidding specific fields in new documents

Similarly, you can prevent clients from creating documents that containspecific fields by usinghasAny()against a list of forbidden fields. This method evaluates to true if adocument contains any of these fields, so you probably want to negate theresult in order to forbid certain fields.

For instance, in the following example, clients are not allowed to create adocument that contains anaverage_score orrating_count field since thesefields will be added by a server call at a later point.

servicecloud.firestore{match/databases/{database}/documents{//Allowtheusertocreateadocumentonlyifthatdocumentdoes*not*//containanaverage_scoreorrating_countfield.match/restaurant/{restId}{allowcreate:if(!request.resource.data.keys().hasAny(['average_score','rating_count']));}}}

Creating an allowlist of fields for new documents

Instead of forbidding certain fields in new documents, you might want to createa list of only those fields that are explicitly allowed in new documents. Thenyou can use thehasOnly()function to make sure that any new documents created contain just these fields(or a subset of these fields) and no other.

servicecloud.firestore{match/databases/{database}/documents{// Allow the user to create a document only if that document doesn't contain// any fields besides the ones listed below.match/restaurant/{restId}{allowcreate:if(request.resource.data.keys().hasOnly(['name','location','city','address','hours','cuisine']));}}}

Combining required and optional fields

You can combinehasAll andhasOnly operations together in your securityrules to require some fields and allow others. For instance, this examplerequires that all new documents contain thename,location, andcityfields, and optionally allows theaddress,hours, andcuisine fields.

servicecloud.firestore{match/databases/{database}/documents{// Allow the user to create a document only if that document has a name,// location, and city field, and optionally address, hours, or cuisine fieldmatch/restaurant/{restId}{allowcreate:if(request.resource.data.keys().hasAll(['name','location','city']))&&(request.resource.data.keys().hasOnly(['name','location','city','address','hours','cuisine']));}}}

In a real-world scenario, you may wish to move this logic into a helper functionto avoid duplicating your code and to more easily combine the optional andrequired fields into a single list, like so:

servicecloud.firestore{match/databases/{database}/documents{functionverifyFields(required,optional){letallAllowedFields=required.concat(optional);returnrequest.resource.data.keys().hasAll(required)&&request.resource.data.keys().hasOnly(allAllowedFields);}match/restaurant/{restId}{allowcreate:ifverifyFields(['name','location','city'],['address','hours','cuisine']);}}}

Restricting fields on update

A common security practice is to only allow clients to edit some fields and notothers. You cannot accomplish this solely by looking at therequest.resource.data.keys() list described in the previous section, since thislist represents the complete document as it would look after the update, andwould therefore include fields that the client did not change.

However, if you were to use thediff()function, you could comparerequest.resource.data with theresource.data object, which represents the document in the database beforethe update. This creates amapDiffobject, which is an object containing all of the changes between two differentmaps.

By calling theaffectedKeys()method on this mapDiff, you can come up with a set of fields that were changedin an edit. Then you can use functions likehasOnly()orhasAny()to ensure that this set does (or doesn't) contain certain items.

Preventing some fields from being changed

By using thehasAny()method on the set generated byaffectedKeys()and then negating the result, you can reject any client request that attempts tochange fields that you don't want changed.

For instance, you might want to allow clients to update information about arestaurant but not change their average score or number of reviews.

servicecloud.firestore{match/databases/{database}/documents{match/restaurant/{restId}{//Allowtheclienttoupdateadocumentonlyifthatdocumentdoesn't//changetheaverage_scoreorrating_countfieldsallowupdate:if(!request.resource.data.diff(resource.data).affectedKeys().hasAny(['average_score','rating_count']));}}}

Allowing only certain fields to be changed

Rather than specifying fields that you don't want changed, you can also use thehasOnly()function to specify a list of fields that you do want changed. This is generallyconsidered more secure because writes to any new document fields aredisallowed by default until you explicitly allow them in your security rules.

For instance, rather than disallowing theaverage_score andrating_countfield, you could create security rules that allow clients to only change thename,location,city,address,hours, andcuisine fields.

servicecloud.firestore{match/databases/{database}/documents{match/restaurant/{restId}{// Allow a client to update only these 6 fields in a documentallowupdate:if(request.resource.data.diff(resource.data).affectedKeys().hasOnly(['name','location','city','address','hours','cuisine']));}}}

This means that if, in some future iteration of your app, restaurant documentsinclude atelephone field, attempts to edit that field would failuntil you go back and add that field to thehasOnly() list in your securityrules.

Enforcing field types

Another effect ofCloud Firestore being schemaless is that there is noenforcement at the database level for what types of data can be stored inspecific fields. This is something you can enforce in security rules, however,with theis operator.

For example, the following security rule enforces that a review'sscorefield has to be an integer, theheadline,content, andauthor_name fieldsare strings, and thereview_date is a timestamp.

servicecloud.firestore{match/databases/{database}/documents{match/restaurant/{restId}{//Restaurantrulesgohere...match/review/{reviewId}{allowcreate:if(request.resource.data.scoreisint&&request.resource.data.headlineisstring&&request.resource.data.contentisstring&&request.resource.data.author_nameisstring&&request.resource.data.review_dateistimestamp);}}}}

Valid data types for theis operator arebool,bytes,float,int,list,latlng,number,path,map,string, andtimestamp. Theisoperator also supportsconstraint,duration,set, andmap_diff datatypes, but since these are generated by the security rules language itself andnot generated by clients, you rarely use them in most practicalapplications.

list andmap data types do not have support for generics, or type arguments.In other words, you can use security rules to enforce that a certain fieldcontains a list or a map, but you can not enforce that a field contains a listof all integers or all strings.

Similarly, you can use security rules to enforce type values for specificentries in a list or a map (using brakets notation or key names respectively),but there is no shortcut to enforce the data types of all members in a mapor a list at once.

For example, the following rules ensure that atags field in a documentcontains a list and that the first entry is a string. It also ensures thattheproduct field contains a map that in turn contains a product name thatis a string and a quantity that is an integer.

service cloud.firestore {  match /databases/{database}/documents {  match /orders/{orderId} {    allow create: if request.resource.data.tags is list &&      request.resource.data.tags[0] is string &&      request.resource.data.product is map &&      request.resource.data.product.name is string &&      request.resource.data.product.quantity is int      }    }  }}

Field types need to be enforced when both creating and updating a document.Therefore, you might want to consider creating a helper function that you cancall in both the create and update sections of your security rules.

servicecloud.firestore{match/databases/{database}/documents{functionreviewFieldsAreValidTypes(docData){returndocData.scoreisint&&docData.headlineisstring&&docData.contentisstring&&docData.author_nameisstring&&docData.review_dateistimestamp;}match/restaurant/{restId}{//Restaurantrulesgohere...match/review/{reviewId}{allowcreate:ifreviewFieldsAreValidTypes(request.resource.data)&&//Otherrulesmaygohereallowupdate:ifreviewFieldsAreValidTypes(request.resource.data)&&//Otherrulesmaygohere}}}}

Enforcing types for optional fields

It's important to remember that callingrequest.resource.data.foo on adocument wherefoo doesn't exist results in an error, and therefore anysecurity rule making that call will deny the request. You can handle thissituation by using thegetmethod onrequest.resource.data. Theget method allows you to provide adefault argument for the field you're retrieving from a map if that fielddoesn't exist.

For example, if review documents also contain an optionalphoto_url fieldand an optionaltags field that you want to verify are strings and listsrespectively, you can accomplish this by rewriting thereviewFieldsAreValidTypes function to something like the following:

  function reviewFieldsAreValidTypes(docData) {     return docData.score is int &&          docData.headline is string &&          docData.content is string &&          docData.author_name is string &&          docData.review_date is timestamp &&          docData.get('photo_url', '') is string &&          docData.get('tags', []) is list;  }

This rejects documents wheretags exists, but isn't a list, while stillpermitting documents that don't contain atags (orphoto_url) field.

Partial writes are never allowed

One final note aboutCloud Firestore Security Rules is that they either allow theclient to make a change to a document, or they reject the entire edit.You cannot create security rules that accept writes to some fields in yourdocument while rejecting others in the same operation.

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 2026-02-18 UTC.