# Security Rules

A public-facing database wouldn't be complete without a security system.

Firestore and Firebase Storage both use Firebase's new security rules syntax, while the original Firebase Realtime Database uses the original JSON security rules syntax. Both systems are easy enough to work with.

The gist of security rules is that you'll be granting read and/or write access to individual nodes of your database.

## Basic Rules

Our Firestore security rules for Fogo, our image-sharing app, are as follows:

```
service cloud.firestore {
  match /databases/{database}/documents {
    match /uploads/{document=**} {
      allow write: if request.auth.token.admin == true ;
      allow read;
    }

    match /users/{document=**} {
      allow read, write: if request.auth.token.admin == true ;
    }
  }
}
```

Let's break these rules down line-by-line.

**service cloud.firestore** — defines the service, in this case it's `cloud.firestore`

**match /databases/{database}/documents** — defines the database; the `{database}` clause indicates that these rules apply to all Firestore databases on the project

**match /uploads/{document=\*\*}** — creates a new rules block to apply to the *uploads* collection and all documents contained therein

**allow write: if requests.auth.token.admin == true ;** — allows write access for authenticated sessions with an `admin` attribute equal to `true` on the auth token, which is also known as the user's JWT

**allow read;** — allows public read access

**match /users/{document=\*\*}** - creates a new rules block for the *users* collection and all documents contained therein

**allow read, write: if request.auth.token.admin == true ;** - allows both read and write access for authenticated sessions with an `admin` attribute equal to `true` on the auth token, which is also known as the user's JWT

## Match blocks

Here's the pattern for match blocks 👇

```
match /my-collection/my-document {

}
```

The document-name fields can be set to wildcard values as well, which looks like this 👇

```
match /my-collection/{allDocuments} {

}
```

If you want a rule to apply to all documents *AND* all sub-collection documents, you need a slightly different syntax:

```
match /my-collection/{allDocuments=**} {

}
```

Notice the `=**` at the end of the wildcard? That's the "recursive wildcard" syntax. If you don't tell your wildcard to be recursive, your match block will not apply to sub-collection documents. Imagine a data structure like `/users/{userDocs}/preferences/{preferenceDocs}`, where you have a collection of Users, and each user has a collection of Preferences. We can think of three types of match blocks for this data structure:

```
match /users/{user} {
  // applies to the user docs, NOT the nested preference docs
}

match /users/{user=**} {
  // applies to just the user docs AND the nested preference docs
}

match /users/{user}/preferences/{preference} {
  // applies ONLY to the preference docs
}
```

You could write the same rules like this:

```
match /users/{user} {
  // applies to the user docs, NOT the nested preference docs

  match /preferences/{preference} {
    // applies only to the preference docs
  }
}
```

See what we did there with the nested rule blocks? Yeah, you can nest match blocks. It's purely optional, but it might be easier to read in some cases.

## Rule types

The basic rule types are `read` and `write`. But each of these rule types can be broken down into sub-types.

* read
  * get
  * list
* write
  * create
  * update
  * delete

### Read rules

The basic `allow read` rule grants both `get` and `list` access to the documents in a collection.

The `allow get` rule allows a user to read a single document, but not list all documents.

And `allow list` allows a user to read an entire collection or query the collection.

There's an funny bit of detail here. Imagine allowing a user to `list` a collection but not `get` a document within it. This would be a strange rule, because that user would still be able to read each individual document... but he or she would have to pull the entire collection rather than one specific document. There might be a use case for this pattern, but we can't think of one.

The `get` and `list` rules would be useful if, for example, you want an admin user to both get and list all of the documents in a collection, but you want regular users to only get certain documents that are specific to them. In this model, you'd have to provide the ID of the document to the user.

Here's how those queries could look:

```javascript
firebase
  .firestore()
  .collection('users')
  .get()
  .then(snapshot => {
    // allowed for an admin user
  })
  .catch(error => {
    // a non-admin user is denied list permission
  });

firebase
  .firestore()
  .collection('users')
  .doc('my-user-id')
  .get()
  .then(snapshot => {
    // a non-admin user can get just one doc
  });
```

### Write rules

The `allow write` rule grants `create`, `update` and `delete` privileges.

The `allow create`, `allow update` and `allow delete` rules are self-explanatory 😊

Imagine a project-management app with three levels of user-security: admins, managers and employees. In this case, you may want to allow employees to update existing projects, allow managers to create and update projects and allow the admins full create, update and delete permissions.

## Conditions

Perhaps the trickiest part of security rules is writing the individual rule conditions.

To start off, you can always declare a rule without conditions:

```
match /dropboxCollection {
  read false;
  write true;
}

match /mailboxCollection {
  read true;
  write false;
}
```

> ***Note:*** Your Cloud Functions and authorized Node.js servers have full read/write access to the entire database, regardless of security rules.

But most apps need write conditions, so security rules have a similar-to-JavaScript DSL (domain-specific language) for defining those conditions.

## Wildcard variables

First off, any wildcards that you declared in your match rules are available as variables.

The following example shows how you could enable users to read their own user documents and write only one preference document: `receiveMarketingEmail`;

```
match /users/{userId} {

  allow read: if request.auth.uid == userId;

  match /preferences/{preference} {  
    allow read: if request.auth.uid == userId;
    allow write: if request.auth.uid == userId && preference == 'receiveMarketingEmail';
  }
}
```

## Request variables

Rule conditions have access to a `request` object that represents that incoming request. You'll be using the `request` object for most rule conditions. Here's a sketch of what that object looks like as JSON:

```javascript
{
  "auth": {
    "uid": "my-unique-user-id-aka-uid",
    "token": {
      "some-custom-claim": true,
      "email": "user@email.com",
      "email_verified": false,
      "phone_number": null,
      "name": "My displayName",
      "sub": "my-unique-user-id-or-uid",
      "firebase": {
        "identities": {
          "google.com": ["first-google-uid", "second-google-uid"],
          "facebook.com": ["first-facebook-uid", "second-facebook-uid"]
        },
        "sign_in_provider": "facebook.com"
      }
    }
  },
  "path": Path,
  "query": {
    "limit": 10,
    "offset": "some-cursor-value",
    "groupBy": {
      "widgetType": true,
      "widgetName": false
    },
    "orderBy": {
      "widgetCreated": "ASC",
      "widgetName": "DESC"
    },
    "resource": Resource
  },
  "time": Timestamp,
  "writeFields": List
}
```

The `request.auth` attribute is mostly primitive values, i.e., strings, numbers, nulls and booleans. Note that you can access custom claims directly off of `request.auth.token`.

Now we get into some custom objects. You'll want to follow links and read the docs.

`request.path` is a [Path object](https://firebase.google.com/docs/firestore/reference/security/#path_2).

`request.query.resource` is a [Resource objects](https://firebase.google.com/docs/firestore/reference/security/#firestore-resource) representing the changes being made by a write.

`request.time` is a [Timestamp object](https://firebase.google.com/docs/firestore/reference/security/#timestamp).

And finally, `request.writeFields` contains a [List object](https://firebase.google.com/docs/firestore/reference/security/#list) of fields being written.

## Resource object

In addition to the `request` object, there's also a `resource` object available. That means that `resource.data` can be compared to `request.resource.data` to identify requested changes.

## Stick with request.auth

The `request.auth` object is by far the most commonly used part of the `request` object, especially when [custom claims](https://firebase.google.com/docs/auth/admin/custom-claims) have been set on `request.auth.token`.

A common custom claim pattern is to set an `admin` flag which can be used like so:

```
match /superSecretAdminStuff/{docs=**} {
  allow read, write: request.auth.token.admin == true;
}
```

## Read the docs

Firebase has excellent docs, and we don't want to compete with such great writing.

The highlights:

* [the Resource object](https://firebase.google.com/docs/firestore/reference/security/#firestore-resource)
* [Functions: exists() and get()](https://firebase.google.com/docs/firestore/reference/security/#functions)
* [Developer-defined Functions](https://firebase.google.com/docs/firestore/reference/security/#developer_defined)
* [Data types](https://firebase.google.com/docs/firestore/reference/security/#data_types)

## Firebase Storage security rules are nearly identical

Firestore's security system is shared by [Firebase Storage](https://firebase.google.com/docs/reference/security/storage/). The objects and data types are identical, but Storage is dealing with binary objects, so it's Resource properties are bit different.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.fullstackfirebase.com/cloud-firestore/security-rules.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
