Mr. Blockchain
Mr. Blockchain

Reputation: 323

Allowing users to only modify their own data on firebase

I am trying to block hackers from modifying or seeing the data on my Firebase database. Users in my database contains the user IDs of all the users in Authentication tab. Can I make the database to only let see data by the user logged in?

This is my database structure:

firebase database structure

enter image description here

I want to allow users to modify their own user ID's entry in "users" and I want to allow only the admin to control "orders". Im using Firebase in a Electron app so client is connecting to firebase in Node.js

Upvotes: 3

Views: 2583

Answers (1)

casieber
casieber

Reputation: 7542

Yes, this is definitely doable using Firebase Database Rules

What you've described seems like it would have three parts, but they we they combine also affects how you need to write them.

I'll start by going over the 3 pieces separately and then will move into combining them.

Read/Write By Only Logged In Users

{
    "rules": {
        ".read": "auth != null",
        ".write": "auth != null"
    }
}

By placing this at the top level of your rules, you will prevent any reading or writing by anyone not logged in through one of the supported Firebase authentication methods.

Users Modifying User Entry

{
    "rules": {
        "users": {
            "$uid": {
                ".write": "auth.uid === $uid"
            }
        }
    }
}

This specifies that under the user path, for each user id (using the $uid syntax to specify it as a variable to be used later), only allow writing when the current authenticated user id matches that same id.

Admin Control Of Orders

{
    "rules": {
        "orders": {
            ".read": "auth != null && auth.token.isAdmin",
            ".write": "auth != null && auth.token.isAdmin"
        }
    }
}

We take a similar approach for orders as we did for users entries, but instead of checking the user id we simply say that only an admin can do reads and writes anywhere under orders.

Putting It All Together

Now, if these rules came together in a way such that more specific rules overrode less specific rules (like CSS selectors, for instance), then we could simply merge all of the above together like this:

{
    "rules": {
        ".read": "auth != null",
        ".write": "auth != null",
        "orders": {
            ".read": "auth != null && auth.token.isAdmin",
            ".write": "auth != null && auth.token.isAdmin"
        },
        "users": {
            "$uid": {
                ".write": "auth.uid === $uid"
            }
        }
    }
}

However, Firebase database rules are somewhat of an inverse of this. Providing access in shallower rules will override any deeper rules attempting to deny access (although it is possible to grant more privileges in deeper rules). So the above will actually give full read/write access to the entire DB by any logged in user.

In light of that, we will need to be more careful when combining these, to ensure that our separate intents stay valid. Most importantly, the first section Read/Write By Only Logged In Users will be the section that requires modification, since it was at the top level.

Luckily, our rules from parts 2 & 3 take care of most of what we were getting from part 1 anyways. This only holds true if there are only orders and users in your db. The only thing we are missing is a read rule on users. It's not entirely clear what sort of rules you want for reading user data, since you only specify that a user can only write his or her own data, so I will assume that all logged in users can read user data.

The merge then becomes:

{
    "rules": {
        "orders": {
            ".read": "auth != null && auth.token.isAdmin",
            ".write": "auth != null && auth.token.isAdmin"
        },
        "users": {
            ".read": "auth != null",
            "$uid": {
                ".write": "auth.uid === $uid"
            }
        }
    }
}

Please note that you will need to duplicate the auth != null rule for read and/or write in other nodes of your db if you have them, since here you only show off orders and users.

Hope that helps!

Upvotes: 9

Related Questions