DEV Community

Cover image for 5 Must-Know Firebase Cloud Firestore Security Rules
Raja Tamil
Raja Tamil

Posted on

5 Must-Know Firebase Cloud Firestore Security Rules

I have been asked by a lot of developers this one question…

Is Firebase safe as the config code is exposed to the browser? 🔥

My answer is Yes and No.

The config code that Firebase provides is meant to be public.

But…

The real security lays in the Security Rules. 👮‍♂️

Having the right security rule in place, you can build a secure web app with the Cloud Firestore without needing your own server at all.

However, if you have your own server or are using cloud functions using Firebase Admin SDK, all security rules will be bypassed.

In that case, you will have to handle security manually in your server-side environment.

Let’s take a look at the SIX common scenarios that you may run into when writing Firestore Security Rules.

Recommended
Learn Firebase Storage Quickly [Guide]

01. Read Permission For Anyone

Let’s say you have a posts collection and you want to show all documents from it to anyone who visits your site. You can do something like this:

service cloud.firestore {    
  match /databases/{database}/documents {      
    match /posts/{docId} {        
      allow read;     
    }    
  }  
} 
Enter fullscreen mode Exit fullscreen mode

Pretty straightforward!

The allow:read gives permission to read all documents in a given path, in this case, /posts/{docId}.

Other operations such as create, update and delete can be a different statement or merged with the read statement depending upon what type of rule you’re trying to write.

But, NEVER use allow:write without additional rules in place.

02. For Authenticated Users Only

Instead of showing the posts to anyone, how about showing them to only authenticated users.

service cloud.firestore {   
  match /databases/{database}/documents {     
    match /posts/{docId} {      
      allow read: if request.auth.uid != null     
    }   
  }
}
Enter fullscreen mode Exit fullscreen mode

You can easily do that by checking to see if the signed-in user’s uid exists or not. The request.auth object has information about the signed-in user. So, you can access uid using request.auth.uid property.

Nice!

The third security rule will enforce that only logged-in users can read or write their own documents, not others and vice-versa.

03. Secure Logged-In User Data

If you’re from an SQL background, this is a one-to-one relationship. One document per user in a users collection.

service cloud.firestore {    
  match /databases/{database}/documents {      
    match /users/{uid} {        
      allow read, write: if request.auth.uid == uid      
    }    
  }  
} 
Enter fullscreen mode Exit fullscreen mode

In the inner match path, you can see the users collection slash the wildcard variable {uid} that basically represents any document that’s inside that collection.

Using this security rule, users can only update their own document if their logged-in user ID is equal to the uid that already exists in the database.

On top of that, you could add an email verification check as a second condition using request.auth.token.email_verified flag.

service cloud.firestore {    
  match /databases/{database}/documents {      
    match /users/{uid}/ {        
      allow read, write: 
        if request.auth.uid == uid &&
           request.auth.token.email_verified == true     
    }    
  }  
} 
Enter fullscreen mode Exit fullscreen mode

04. Never Trust The Client And Validate Data

Let’s say you have a post collection and each document inside it has a title, content, author, author_id, etc. The author_id would be an actual user ID.

alt text

I often find that it’s easier to understand when showing the data structure before showing the security rule.

Sometimes, you will want to validate the incoming request data before saving it into the database using the request object.

Let’s add a security rule to validate data before allowing users to add new posts to the Cloud Firestore.

Continue Reading...

Top comments (0)