I am using Firebase Auth and read a lot of documentation on security rules, custom claims, cloud functions, but I've really gotten more confused.
Consider the following data structure
{
"company": {
"idCompany1": {"data": "Restricted to Company1s users"},
"idCompany2": {"data": "Restricted to Company2s users"}
},
"users": {
"idUser1": {
"companies": {
"idCompany1": true
}
},
"idUser2": {
"companies": {
"idCompany1": true,
"idCompany2": true
}
}
}
}
I would like to implement a simple rule in the Firebase Console (Firebase Security Rule) without modifying my Data Structure.
The Rule I would like to configure is: A user can only read or write information in the companies to which it belongs (users/$idUser/companies/$idCompany === true on path company/$idCompany)
At this moment I have only configured:
{
"rules": {
"company" : {
".read": "auth != null",
".write": "auth != null",
}
}
},
"users" : {
"$user_id" : {
".read": "auth != null",
".write": "auth.uid === $user_id"
}
}
How can I configure this Firebase security Rule in the Firebase Console?
It sounds like you're looking for:
{
"rules": {
"company" : {
"$companyid": {
".read": "root.child('users').child(auth.uid).child('companies').child($companyid).val() === true"
}
}
}
}
This will allow the user to read /company/$companyid for any company where it is listed in their profile.
Note: you won't be able to read /company itself, as rules are not filters.
Related
I have a website that uses Firebase Realtime Database. It usually sends me e-mail about insecure rules warning. I searched about this here and Firebase Documantation, but when I write other rules, it gives me such error:
Error saving rules - Line 10: String can't contain ".", "#", "$", "/", "[", or "]"
{
// Allow anyone to read data, but only authenticated content owners can
// make changes to their data
"rules": {
"some_path/${uid}": {
".read": true,
// or ".read": "auth.uid != null" for only authenticated users
".write": "request.auth.uid == uid"
} SHOWS ME ERROR IS HERE.
}
}
I am using this rules for now:
{
"rules": {
".read": true,
".write": false
}
}
here is one picture that I try one of other rules called Mixed public and private access.
I will be very glad if anyone can help me.
The syntax does not seem correct to refer to a child resource, check below syntax to achieve the desired effect
{
"rules": {
"some_path": {
"$uid": {
".write": "$uid === auth.uid"
}
}
}
}
https://firebase.google.com/docs/database/security
I have a firebase database that looks like this
Cards
Group1
- 0
- isLight
- likes
- shares
- 1
- isLight
- likes
- shares
i need to write a rule that permits writing likes and shares only and close it for everything else , with read allow , so i wrote
{
"rules": {
"Cards": {
".write": "false"
"Group1" : {
"0": {
"likes" : {
".read": "true",
".write": "true"
},
"shares" : {
".read": "true",
".write": "true"
}
}
}
}
}
}
I don't want to statically write Group1 and 0 as there are no limit to their count so i need to substitute them with something general but i don't know it
Can you pls try it with this:
{
"rules": {
"Cards": {
"$Group" : {
"$index": {
"likes" : {
".read": "true",
".write": "true"
},
"shares" : {
".read": "true",
".write": "true"
}
}
}
}
}
}
I try to return to the user the list of his chat with a rule.
So I don't know the id of the conversations.
I have tried several methods but none of them work because you have to know the chat id.
Database :
{
"Chats" : {
"-MPnCVZSVi5C3QbHnXl3" : {
"messages" : [ {
"createdAt" : 1609324431814,
"text" : "Gggwdhj",
"user" : "3Oi1atf8l2P4Vgsb8tZOGxpUg7q2"
} ],
"name" : "toto",
"users" : {
"3Oi1atf8l2P4Vgsb8tZOGxpUg7q2" : true
}
}
}
}
Rules :
{
"rules": {
"Chats": {
".read": "data.child('users').hasChild(auth.uid)",
".write": "true"
}
}
}
Result :
But when I access from the react native application. Access to chats does not pass for an authenticated user(uid : 3Oi1atf8l2P4Vgsb8tZOGxpUg7q2)
*The read failed: Error: permission_denied at /Chats: Client doesn't have permission to access the desired data.
Rules :
{
"rules": {
"Chats": {
"$uid":{
".read": "data.child('users').hasChild(auth.uid)",
".write": "true"
}
}
}
}
Query :
firebase.database().ref('Chats')
.limitToLast(20)
.on('child_added', snapshot => {
callback(this.parse(snapshot))
}, function (errorObject) {
console.log("The read failed: " + errorObject);
});
If you want to apply a certain rule/set of rules to all child nodes, you can use a $ wildcard like this:
{
"rules": {
"Chats": {
"$chatId": {
".read": "data.child('users').hasChild(auth.uid)",
".write": "true"
}
}
}
}
For more on this, see the Firebase documentation on $ wildcard variables. In general I'd recommend reading the Firebase docs on security rules end-to-end as they're not that long, and a few hours spent there now will save you much more time down the line.
EDIT: this will also not work if I will set ".read": "true"
in any child or any sub-tree including the rules root (this is not showing here in the examples).
In my app, which manage user's wedding details such as guests, I want to let the guests write to the "arrive" field only if the "invited" field is exists (actually if it will be true , but I checked if it exists just for testing). However, I didn't manage to do this since in the Firebase console it's says that the simulated set is denied :
The rules in the Firebase console:
{
"rules": {
"Users": {
"$uid":{
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
},
".indexOn": "email"
},
"Guests":{
"$uid":{
"$guest_id":{
"arrive":{
".read": "$uid === auth.uid",
".write": "root.child('Guests/'+ $uid + '/' + $guest_id +'/invited').exists()"
}
}
}
}
}
}
The JSON example I wrote in the Rules Playground in the console:
{
"Guests": {
"user_1": {
"guest_1": {
"arrive": false,
"invited": true
}
}
}
}
The location path in the Rules Playground:
/Guests/user_1/guest_1/arrive
I tried several approaches and they didn't work. For example:
".write": "data.parent().child('invited').exists()"
or
".write": "root.child('Guests').child($uid).child($guest_id).child('invited').exists()"
I have the following case, how can I deny access to update (overwrite) the node if it already exists? For example, the request for additions to friends, I want that, this feature was executed once because it set rules in the database, but they do not work. How can this be fixed?
Rules
// friends
"friends": {
"$ownerID": {
"friendIncomingRequests": {
"$secondUserID": {
".write": "!data.exists()" // Only allow new nominations to be created
}
},
"friendOutgoingRequests": {
"$secondUserID": {
".write": "!data.exists()" // Only allow new nominations to be created
}
}
}
}
Data
"friends" : {
"8OdvaGQfMVdJrlCxdc5pOaj09hy2" : {
"friendOutgoingRequests" : {
"mp9pfsfVQKavwYddjYYPC5Ja9N93" : {
"timeStamp" : 1.495514876872129E9,
"userID" : "mp9pfsfVQKavwYddjYYPC5Ja9N93",
"userName" : "Tim C."
}
}
},
"mp9pfsfVQKavwYddjYYPC5Ja9N93" : {
"friendIncomingRequests" : {
"8OdvaGQfMVdJrlCxdc5pOaj09hy2" : {
"senderID" : "8OdvaGQfMVdJrlCxdc5pOaj09hy2",
"senderName" : "Alexsander K.",
"timeStamp" : 1.495514876872129E9
}
}
}
},
Update
I think the problem is in this code, since I have this code also in the rules. But how can I fix it?
"rules": {
".read": "auth != null",
".write": "auth != null",
}
Update 1: Here are all the rules. I need to make a specific write rule (updates) only in friends. I saw examples that for each individual branch of their rules, but if I need to do some specific rules for one branch, and for the rest of the database you need standard rules how should I do this better?
{
"rules": {
".read": "auth != null",
".write": "auth != null",
// card location
"cardLocation": {
// Allow anyone to read the GeoFire index
//".read": true,
// Index each location's geohash for faster querying
".indexOn": "g",
},
"cards": {
".indexOn": "ownerID"
},
"userListEvents": {
"$uid": {
".indexOn": "isConfirmed"
}
},
"userImages": {
"$uid": {
"userProfileImages": {
".indexOn": "isoDate"
}
}
},
// tags
"userTags": {
"$uid": {
".indexOn": "isSelected"
}
},
// people search
//
"userLocations": {
".indexOn": "g"
},
// friends
"friends": {
"$ownerID": {
"friendIncomingRequests": {
"$secondUserID": {
".write": "!data.exists()"
}
},
"friendOutgoingRequests": {
"$secondUserID": {
".write": "!data.exists()"
}
}
}
}
}
}
I think the problem is in this code, since I have this code also in the rules. But how can I fix it?
"rules": {
".read": "auth != null",
".write": "auth != null",
}
Yes, your thought is correct. Firebase .read and .write rules cascade. So you should put every .read and .write on each child node of your data structure. Something like that:
{
"rules": {
//skip this
"someNode": {
".read": "auth != null",
".write": "auth != null"
},
// friends
"friends": {
"$ownerID": {
"friendIncomingRequests": {
"$secondUserID": {
".write": "!data.exists()"
}
},
"friendOutgoingRequests": {
"$secondUserID": {
".write": "!data.exists()"
}
}
}
}
//...
}
}