Firebase rules: Unknown variable '$uid' - firebase

I want user to only access their own content, except for one child node: common
In common child node I want all signed in users to have access.
I have made the following rules:
{
"rules": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
},
"common" : {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
Firebase gives me the error:
Error saving rules - Line 8: Unknown variable '$uid'.
The error appears in this line: ".read": "auth != null && auth.uid == $uid",

Based on your question, this is your desired database structure:
{
"userIdA": { // anything here can be written by only userIdA
"name": "Tom", // this is just example data
"location": "London",
/* ... */
},
"userIdB": { // anything here can be written by only userIdB
"name": "Sarah",
"location": "New York",
/* ... */
},
/* ... other user data ... */
"common": { // anything here can be written by signed in users
"data1": "some value",
"data2": "some other value",
}
}
The rules for this structure would be:
{
"rules": {
"common" : {
".read": "auth != null", // logged in users can read
".write": "auth != null" // logged in users can write
},
"$uid": { // $uid will be the value of any key, that isn't listed above it (in this case, anything other than "common")
".read": "$uid === auth.uid", // only the matching user can read
".write": "$uid === auth.uid" // only the matching user can write
}
}
}
Note: This data structure isn't very secure. Allow read/write access to only what you need in your database. With this structure, any user could come along and open up their console and delete everything under "/common". You may consider adding ".validate" rules to make sure certain keys (such as "/common/data1") are only strings.

The $uid must be inside users Document like the example below :
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}

Related

Can I access data from firebase's real time database on security rules

I have a token stored in my /users/UID object, and I want to check if the token provided in the request matches it. How can I do this?
At the moment, I have this:
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid",
"files": {
".write": "newData.child(\"token\").val() === \"ZnYKcbTIaN466iQ\"", //
".read": "$uid === auth.uid"
},
}
},
}
}
The code above returns true, but the token changes periodically. Can I, somehow, access this information in my database?
I got it! To check was quite simple, you just need to use the data object
".write": "newData.child(\"token\").val() === data.child(\"token\").val()"

Firebase Rules: We've detected the following issue(s) with your security rules

appreciate this looks like this is been answered various times for individual requirements. Completely new to Firebase and I want to get some insight into this. I have been presented with the message from Firebase.
We've detected the following issue(s) with your security rules:
any logged-in user can read your entire database
any logged-in user can write to your entire database
My current rules look like this:
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"items": {
".indexOn": "ownerId"
},
"events": {
".indexOn": "ownerId"
},
"contacts": {
".indexOn": "ownerId"
}
}
}
Based on the documentation, Do I simply need to do this?
{
"rules": {
".read": "auth != null && auth.uid == $uid"
".write": "$user_id === auth.uid",
"items": {
".indexOn": "ownerId"
},
"events": {
".indexOn": "ownerId"
},
"contacts": {
".indexOn": "ownerId"
}
}
}
Will users still be able to access their own (previously) written data prior to making the change while enforcing the security rules from Firebase.
Apologies if this a silly question, but got a lot of data which I cannot let users not have access to.
Thanks
As firebase documentation says:
Sometimes, Rules check that a user is logged in, but don't further restrict access based on that authentication. If one of your rules includes auth != null, confirm that you want any logged-in user to have access to the data.
So you have to get rid of this part down under the rules part:
".read": "auth != null",
".write": "auth != null",
And use any of these approaches: Content owner only, Path-delineated access or Mixed public and private access.
For example:
{
"rules": {
"products": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid",
".indexOn": ["creatorId", "isActive"]
}
},
"stores": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid",
".indexOn": ["creatorId", "isActive"]
}
},
"orders": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid",
}
},
}
}

Firebase Database Rules to match row

I am using a Firebase Realtime Database. I have the following data:
I also have the rules:
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"chat": {
"$key": {
".read": "data.child('memberId1').val() === auth.uid && data.child('memberId2').val() === auth.uid",
".write": "data.child('memberId1').val() === auth.uid || data.child('memberId2').val() === auth.uid"
}
},
The initial rule works perfectly:
".read": "auth != null",
".write": "auth != null",
Problem
The following 2 rules have no effect.
"chat": {
"$key": {
".read": "data.child('memberId1').val() === auth.uid && data.child('memberId2').val() === auth.uid",
".write": "data.child('memberId1').val() === auth.uid || data.child('memberId2').val() === auth.uid"
}
},
As you can see, in order to test these rules, in the first rule, I have made an impossible condition of memberId1 and memberId2 both equal to the users uid. As a result I would expect it to fail.
If I remove:
".read": "auth != null",
".write": "auth != null",
and just have:
"chat": {
"$key": {
".read": "data.child('memberId1').val() === auth.uid || data.child('memberId2').val() === auth.uid",
".write": "data.child('memberId1').val() === auth.uid || data.child('memberId2').val() === auth.uid"
}
},
Then access is denied. Even if I change it to:
"data.child('memberId1').val() === 'h6qQg5YfQveTaCyBEXwDMSJPqwk1'
The following is also denied:
"chat": {
"Ko7w9XTtuRVN4p6CMp7": {
".read": true,
Question
How should I structure the rules to allow that a user may only access a row where their uid matches either memberId1 or memberId2?
Thanks
UPDATE
I have the following code:
findChats(): Observable<any[]> {
return this.af.database.list('/chat/', {
query: {
orderByChild: 'negativtimestamp'
}
}).map(items => {
const filtered = items.filter(
item => (item.memberId1 === this.me.uid || item.memberId2 === this.me.uid)
);
return filtered;
});
}
My question is similar to this one. I try the following with no success:
{
"rules": {
"chat": {
"$id": {
".read": true
}
},
Firebase rules are atomic. So if you try to read /chat (and thats what you are currently doing) it will only check the /chat branch rules. Since you dont have any rule in /chat it goes for the default thats is not giving access. Therefore, your rules would only be evaluated in case you were trying to read /chat/chatId.
One possible solution you could go for is to store a list of chats which each user is part of. So you can keep your current chat branch but store another branch in the database with the following structure:
user_chats: {
uid1: {
chatId1: true,
chatId2: false
}
uid2: ...
}
And rules:
"user_chats": {
"$uid": {
".read": "auth.uid === $uid",
".write": "auth.uid === $uid"
}
}
Then you could keep your chat rules like you already have them but first get the data from /user_chats/uid and then for each chatId retrieved you you will need to read on chat/chatId.

Firebase user permission

I have two mega parent nodes, but I am currently unable to write to the second one.
-users
uid
some other info
uid
-secondParent
child
uid
child
uid
I would like the user to be able to write to his own child of secondParent. Read and write permissions are working correctly for the users parent node, but I can't get it working for the secondParent.
The rule I have currently is:
{
"rules": {
"users": {
"$uid": {
".read": "auth != null",
".write": "$uid === auth.uid",
}
},
"parentdNode": {
"$childID":{
".read" : "auth != null",
"$uid":{
".write": "$uid === auth.uid",
}
}
}
}
}
Simulation failure below:
You have to write rules for each parents to enable permission
{
"rules": {
"users": {
"$uid": {
".read": "auth != null",
".write": "$uid === auth.uid",
}
},
"parentdNode": {
"$childID":{
"$uid":{
".read" : "auth != null",
".write": "$uid === auth.uid",
}
}
}
}
}
According to the screenshot, you are trying to write {"uid":"X","property":"Y"} to /parentNode/someNode. The rules give permission to write {"property":"Y"} to /parentNode/someNode/65ef..aa62.
JSON trees come with key/value pairs. There is no key uid in the scheme you presented, there is a $uid which is replaced by the a value from the path you are accessing.
It may still be a bit confusing, but I hope this points to clarifying ideas.

Security rules for posting to a user's subdirectory in Firebase

The following are my Firebase security rules:
security-rules.json
{
"rules": {
"users": {
"$uid": {
".write": "auth.uid === $uid",
".read": "auth.uid === $uid"
}
}
}
}
It works fine when my path ends with the users directory. As in:
https://my-firebase.firebaseio.com/users/my-user-id.json
But when I try to post directly to a subdirectory, as follows:
https://my-firebase.firebaseio.com/users/my-user-id/settings.json
it doesn't work.
Question
What do I need to do to the security-rules.json file (or anything else) to be able to write directly to a user's subdirectory?
Edit:
Someone suggested, "just extend your rule to include settings." So I tried this:
security-rules.json
{
"rules": {
"users": {
"$uid": {
".write": "auth.uid === $uid",
".read": "auth.uid === $uid"
},
"settings": {
".write": "auth.uid === $uid",
".read": "auth.uid === $uid"
}
}
}
}
Which throws the following error:
9:30: Unknown variable '$uid'.
10:31: Unknown variable '$uid'.
This works in the simulator:
{
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid",
"settings": {
}
}
}
}
}
After further testing, I found the security rules contained in the OP also work in the simulator:
security-rules.json
{
"rules": {
"users": {
"$uid": {
".write": "auth.uid === $uid",
".read": "auth.uid === $uid"
}
}
}
}
There is no need to add additional rules for writing deeper into the node tree. The highest level permissions are sufficient.
Aside: My problem appears to be something other than the security rules I'm using. I must do more research, experimentation and testing.

Resources