Search code examples
javascriptfirebasegoogle-cloud-firestorefirebase-security

Can someone please explain to me why we need Firebase security rules when I can literally write rules in my client code?


I don't know if my question is inside the proximity of what I should be asking on stack overflow but if so...

Why do we need to write security rules in 'Firebase "Rules"' when I can literally just go into my client code and say:

db.collection("users").get().then(res=> {
  res.docs.map(user => {
     if (user.data().uid !== auth.currentUser.uid) {
        // do something I'm about to put in this code snippet
     }
  })
})

Like, can someone just get in my client-side code and write whatever they want and that's why we need to write code in the security rules within the Firebase console?

It also confuses me why we need Firebase functions when we can simply do the logic on the client-side although I can understand some stuff needs to be done server-side.

But just for the scope of this question, can someone explain to me clearly why we can't just write our security inside of our code to make things work?

Hopefully I was thorough with the info. Thanks.


Solution

  • Firebase also has a REST API which allows anyone to make requests to your Firebase services directly without any of your code in play. So even if reverse engineering and modifying the code was impossible, there's the REST API.

    You must not trust client applications (especially web apps) and always validate the incoming data and ensure only authorized users can modify it.


    How would they get the information needed to make API calls to my database though? And wouldn't they need a key?

    If you check the Firebase config, it contains an API key which is used to identify your Firebase project only and there's no risk involved in that being visible.

    Now that anyone on the internet knows address of your database, they can use it with REST API if you don't have any security rules setup.


    Do note that after running the db.collection("users").get() query, all the documents have been fetched already (and data should be visible in network tab) from Firestore and then you are just looping over all the documents to find one that matches the current user's UID.

    This query without security rules is insecure (unless listing users is a feature of your application):

    db.collection("users").get().then(res => {
      const user res.docs.find(user => user.data().uid === auth.currentUser.uid)
    })
    

    Instead you should use queries or access user specific documents and have security rules as shown below to ensure a user can read/write their own data only:

    db.collection("users").doc(auth.currentUser.uid).get().then(res => {
      console.log("user:", res.data())
    })
    
    // Security rules
    match /users/{userId} {
      allow read, write: if request.auth.uid === userId;
    }