I must be missing something obvious?
How do I setup firebase security rules so:
any user can ONLY read and create new data
admin/auth can ALSO delete the data
I can't see anywhere in the documentation the ability to have multiple ".write" rules for the same directory...
{
"rules": {
".read": true,
// this only occurs if "auth === null" otherwise should be full access.
".write": "!data.exists() && newData.exists()"
}
}
Related
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
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
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!
I have a database like this:
The first key is the userId, has to be connected, and the next keys only him can read and write. How I can manage the rules to be safe and no one can't see the key of each other ? I begin with that but I don't think is enough
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
Because you are using the user ID as a key you can use it in your rules to make sure users can only read/write to their own nodes like this:
{
"rules": {
"$user_id": {
".write": "$user_id === auth.uid",
".read": "$user_id === auth.uid"
}
}
}
For more information you can take a look at the firebase docs about User Based Security and Securing Data. For a more extencive answer about linking users to their data you can take a look at my answer here.
I am trying to set Firebase security rules as:
No one can read the data
Anyone can write data, new record is under
unique identifier
No one can overwrite current data
No one can delete data
The structure of the database is:
<db_name>
users
-L09I7kaAYExzzxB3N82 // this is unique ID generated by push()
....
My current rules are:
{
"rules": {
".read": "auth != null",
".write": "auth == null"
}
}
How to set it up?
Thanks!
Something like this:
{
"rules": {
".read": false,
"users": {
"$uid": {
".write": "newData.exists() && !data.exists()"
}
}
}
}
I'd recommend reading the Firebase documentation, specifically the section on new data vs existing data.
My app allows anyone to write a new message (the message cannot be updated or deleted), which should then only be visible to authenticated users. The authenticated users can edit the data (which will include things like flag as important, etc.). Think of the app like a private suggestion box (anyone can submit a suggestion but only the admins can view the submitted suggestions). I'm using the Firebase simulator and the following fails but it shouldn't:
Firebase Simulator
Write
Location: messages/
Authenticated: false
Data (JSON)
{
"key": "value"
}
Firebase Database Rules
{
"rules": {
"messages": {
"$message": {
".read": "auth !== null",
".write": "!data.exists() || auth !== null",
},
},
"users": {
".read": "auth !== null",
".write": "auth !== null"
}
}
}
I think that's because you're testing with messages/ whereas only writes to messages/{message-id} would be allowed. Try writing to messages/somethingrandom.
I'm working on a Firebase rule configuration to control read/write access to my database. I had more rules written originally, but I've pared things down during troubleshooting. Here is my current rule configuration:
{
"rules": {
"developers": {
"$dev": {
".write": "!data.exists() && auth != null",
".read": "auth.devBucket === $dev",
"$proj": {
".read": "auth.devBucket === $proj",
"shared": {
".write": "!data.exists() || (auth.devBucket === $dev && auth.projBucket === $proj)"
}
}
}
}
}
}
What I'm trying to do is allow users of the Firebase to create a $dev node, $proj node, and shared node as long as they don't already exist and the user is authenticated. Then, I want to allow a user to have free write access within the shared node as long as their auth token's devBucket matches the $dev node they're writing within and their auth token's projBucket matches the $proj node they're writing within. I'm using the Firebase custom auth system for Android and I've loaded my tokens with these devBucket and projBucket variables. Authentication is definitely working according the my logcat, but I'm definitely getting permission denied errors with my current rules. I've been pouring over the Firebase Rule documentation and questions here for days and I am still puzzled as to the nuances of how their rule system works.
According to the documentation rules carry through to lower levels of nesting in the JSON, I'm just having trouble understanding how I can write a rules that allows a node and it's children to be created once, but also allows any number of children to be written or overwritten under shared if you're properly authenticated.
Does anyone have any idea how I could write rules to accomplish what I'm trying to do?
EDIT: I think it's also worth mentioning that I'm getting permission denied errors when I try to point listeners to my nodes too.
I figured out a configuration that worked for me.
{
"rules": {
"developers": {
".write": "!data.exists() || auth != null",
".read": "auth != null",
"$dev": {
".write": "!data.exists() || (auth != null && auth.devBucket == $dev)",
".read": "auth != null && auth.devBucket == $dev",
"$proj": {
".write": "!data.exists() || (auth != null && auth.projBucket == $proj)",
".read": "auth != null && auth.projBucket == $proj"
}
}
}
}
}