So, I have an app where users can order the cakes and do other profile management, the rules looks like below:
{
"rules": {
"cakes" : {
".read": true,
".write": false
},
"users": {
"$user_id": {
".read": "auth != null && $user_id === auth.uid",
".write": "auth != null && $user_id === auth.uid"
}
}
}
}
Simply, they mean any one can read the cakes node (but no one can write). And an authenticated user can see or write to his on node.
This is good so far.
Now, my requirement is: When someone places an order through the app then i need to store it to firebase db in a top level node (lets say it orders). The question is what kind of security would be placed on orders node?
In functional definition: The app should be able to create new orders as user checks out, no one except seller should be able to read those orders, only seller should be able to have update access to a order.
If you want everybody to be able to write orders, and nobody able to read, the rules are simply the inverse of the ones for cakes:
"rules": {
"orders" : {
".read": false,
"$orderId": {
".write": true
}
},
With this anyone can push new data under /orders. And as long as you use push() to generate the new keys, you're guaranteed that they'll never conflict.
With these rules only a system-level admin can read the data. That is: you can read it in the Firebase Console, or someone can read it if they use the Admin SDK.
You might want to open it up for reading a bit more, e.g. by having the concept of an application-level administrator. Say that your UID is uidOfVik, you could model a list of admins in your database:
admins: {
uidOfVik: true
}
Now you can allow only admins to read the orders with:
"rules": {
"orders" : {
".read": "root.child('admins').child(auth.uid).exists()",
"$orderId": {
".write": true
}
},
Related
I am struggling with the security rules on the firebase realtime database. My database structure is as following:
On the first level you have Chats. On the second level there are the Chat partners (a concatenated string with user IDs of chat partners). On the third level you have the messages. And on the last level there are the variables datetime, userid and message.
My question is, how can I get into the second child node, e.g. check if the auth.uid is within the concataneted string. My idea was to give the users read access, if the userid is within the chatpartners string, to ensure that only the chatpartners can read their messages. Or is this a thinking error?
I have tryid a lot of things, however no success:
"Chats":{
".read": "root.child('Chats').val().contains('auth.uid')"
}
#Update
{
"rules": {
"Chats": {
"$chatid": {
".read": "$chatid.contains(auth.uid)",
".write": "auth != null"
}
},
"Suchencards": {
".read": "true",
".write": "auth != null"
},
"UserData": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
I am using the playground on firebase console to check if I get true or false, however in that case I get false.
#Update 2
Screen1
Screen2
You can only access data in your rules if you know the exact path to that data, so you won't be able to access all chats from a rule on /Chats. Trying to do so typically means that you're trying to define your rules on the wrong level.
For example, if you want to allow a user to read a specific child of Chats, you'll need to define rules on that level:
"Chats":{
"$chatid": {
".read": "$chatid.contains(auth.uid)"
}
}
While the above will work for accessing a specific room, you will not be able to use this to query for all chat rooms that a user has access to (as Firebase queries don't support a "contains" operation). Have a look at the userChatrooms node in my answer here for a better model for tracking the chat rooms for a user: Best way to manage Chat channels in 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
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 am working on the app that I need to connect to the dev firebase.
This firebase has database rules as follows:
"rules": {
// no read access at root level
".read": "auth.uid === 'emailaddressgmailcom'",
".write": false,
What I cannot understand is how auth.uid is specified to be an exact email address?
As far as I tried I only get unique uid provided by Google. (set of numbers and letters)
Hence I can never pass the auth to read from the database, unless I specify my exact uid given by Google in the databse rules, which is not an option because there will be another user who needs an access to db and I do not know his uid.
auth is one of the predefined variables.
By doing auth.uid, you get the user id ("guaranteed to be unique across all providers").
You need, in your Security Rules to use it to defined the access rights of a given user to one or more given resources, as explained here in the doc.
You could compare it to a fixed value, if a certain resource shall be read by a unique user:
".read": "auth.uid === 'HGH656675FHGFGHF3454'"
but usually you compare it to some parts of the path of the node/resource you want to protect, like for example:
{
"rules": {
"users": {
"$user_id": {
// grants write access to the owner of this user account
// whose uid must exactly match the key ($user_id)
".write": "$user_id === auth.uid"
}
}
}
}
This is how you should do to solve your problem "there will be another user who needs an access to db and I do not know his uid".
I would suggest you read the entire section about RTDB Security Rules form more details: https://firebase.google.com/docs/database/security
Please try below rules
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
// These rules grant access to a node matching the authenticated
// user's ID from the Firebase auth token
I have an object called 'Service' This can be read by anyone but changes can only be made by the owner. My firebase rule for this is:-
"Service": {
".read": true,
"$uid": {
".write": data.child('owner').val() == auth.uid"
}
}
Service has a child called 'owner' which is == to the users UI when logging in through firebase Auth.
I also have a User object which can make a Service as a favourite. I'm saving these in the user object as an array of [businessKey:true].
However, I've been asked to also save in the Service object the reverse relation of what users have favourited it. So an array However as a user isn't always the owner of a service I come into a permissions error. I'm trying to write rules that allow anyone to write to one child but not the others.
I have tried...
"Service": {
".read": true,
"$uid": {
".write": data.child('owner').val() == auth.uid" || data.child('users').val() != root.child('users').val()"
}
}
this is would allow a write if the user was the Service owner or just changing the child 'users' The effect was that any user was able to write to anything.
I've also tried
"Service": {
".read": true,
"$uid": {
"$users": {
".write" : true,
},
".write": "data.child('owner').val() == auth.uid"
}
}
thinking this would always allow a write to 'users' and any other child if user was owner.
I'm pretty new to firebase and this rules syntax in general so I'm probably making some glaring error! If what I want to achieve possible? what have I got wrong?
I allow login with Google to my Firebase web app.
I control access to the database by the auth.uid:
{
"rules": {
"users": {
"$uid": {
".read": "auth.uid === $uid",
".write":"auth.uid !== null",
"images": {
".read": "auth.uid === $uid",
".write":"auth.uid === $uid",
},
...
I want to enable other users in the user's team to access his/her images. I went through the docs but couldn't find a way to accomplish that. Any ideas?
Security rules are able to read data from other keys, so it's possible to construct rules that are based upon the existence of a key (i.e. membership of a team).
What's below is a small fragment of the Bolt rules that I've used for a Firebase database:
path /teams/{$teamKey}/members/{$userId} is Boolean {
...
}
path /users/{$userId}/shares/{$teamKey} {
...
read() { root.teams[$teamKey].members[auth.uid] !== null }
}
The JSON would look something like this:
...
"users": {
"$userId": {
...
"shares": {
"$teamKey": {
...
".read": "root.child('teams').child($teamKey).child('members').child(auth.uid).val() != null",
...
Hopefully, that will make some sense. Basically, there is a key for a team and it contains user ids (with boolean values). And read access to shared information under a user's key is granted to other team members by verifying their membership - that is, by checking for the existence of a user id key under the team key. Essentially, you store the data that drives the security rules in the database itself.
You don't have to use Bolt, but I find it much easier to manage than the JSON representation. The Bolt language documentation contains information on the RuleDataSnapshot Methods for both the Bolt definitions and the JSON definitions.