Firebase security rules with wildcards - firebase

I've got a data structure like this:
How can I access /Restaurant/-KK37k6g5cYYippEHpZ3/User/-KK37k6g5cYYippEHpZ4/id's value within the firebase security rules? The two push keys should be wildcards. I need something like this:
"Restaurant": {
"$id": {
".read": "auth.uid != null",
".write": "data.child($id).child('User').child($anotherWildcard).child('id').val() === auth.uid"
}
}

Not sure if I fully understood what you are asking for but here goes my thoughts.
The first problem in your rule is that you are specifying child($id) but you already are inside the $id. it is implicit in your data that you are referring to $id.
To resolve your main problem you wont need another wildcard. You can just use hasChild to verify if the auth.uid is inside restaurant/user.
"Restaurant": {
"$id": {
".read": "auth.uid != null",
".write": "auth.uid != null && data.child('User').hasChild(auth.uid)"
}
}

Related

Firebase Security Rules newData does not work

I'm trying to restrict the "Stores" write to the owner only, but the "write" rules does not seem to work
"Stores": { // restrict "Stores" write to the owner only
".read": "true",
".write": "auth.uid !== null && auth.uid === newData.child('ownerID').val()"
}
... and surprisingly neither does this..
".write": "newData.child('ownerID').exists()"
However it works with this...
".write": "auth.uid !== null"
But it is not as secure as how I want it. Can anyone help please?
You've defined the rule on the wrong level. Right now you're controlling who can write to the /Stores node. But what you want to do, is control who can write an an individual store, so /Stores/$storeid.
Something like:
"Stores": {
"$storeid": {
".write": "auth.uid !== null && auth.uid === newData.child('ownerID').val()"
}
}

How to set indexOn rule on firebase with auth.uid variable?

I am trying to set a rule on a node in firebaseDatabase, but I get error
Error saving rules - Line 85: Key names can't contain ".", "#", "$",
"/", "[", or "]" (unbound names start with "$")
As I understand auth.uid is a global variable for the current logged in user. How can I fix this?
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"notifications/auth.uid": {
".indexOn":["createdAt"]
}
}
}
If you're trying to store notifications for each user under their auth.uid and allow querying those by defining an index, then you're looking for these rules:
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"notifications": {
"$uid": {
".indexOn":["createdAt"]
}
}
}
}
The $uid here is a wildcard, and applies to each node under notifications. To learn more about this, see Using $ Variables to Capture Path Segments.
This is the issue
"notifications/auth.uid"
as it's treating everything inside the quotes as a string so the period is causing the error and paths cannot include a period character. Also, it will not resolve the auth.uid as it's just a string, not the variable you want. You could do something like
root.child('notifications').child(auth.uid) {...
or even
root.child( 'notifications/' + auth.uid ) {...

How can I give write permission to a specified user in Firebase?

I have a mobile application which reads the data from the firebase server without firebase login/authentication (posts and news) and I want to create an admin webpage where I can log in and add, or modify news, so I need a write permission there. My rules are currently:
{
"rules": {
".read": true,
".write": "auth !== null && ?????
}
}
Can I write something like "user.emailAddress == 'mail#example.com'"?
You can create a users table on database like
{
"users":{
"your UID":{
"isAdmin": true
}
}
}
Then edit rules :
{
"rules": {
".read": true,
".write": "auth.uid != null && root.child("users").child(auth.uid).isAdmin === true"
}
}
You might want to start by reading the documentation about securing user data. There is a lot to know here.
One possibility is using the known user's uid to restrict access. The auth.uid variable contains the uid.
".write": "auth.uid == 'the-known-uid'"
Also you can use auth.token to access some other things about the user, including email address (which may not be present):
".write": "auth.token.email == 'the#email.address'"
You can also use custom authentication tokens, which also is covered in the documentation.
Create database:
{
"users":{
"your UID":{
"isAdmin": true
}
}
}
Set rules:
Wrong:
{
"rules": {
".read": true,
".write": "auth.uid != null && root.child("users").child(auth.uid).isAdmin === true"
}
}
Right:
{
"rules": {
".read": true,
".write": "auth.uid != null && root.child('users').child(auth.uid).child('isAdmin').val() === true"
}
}

Firebase rules & security

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.

How to create Firebase tables without separating every single field...for security?

So I'm delving into Firebase security rules and as far as I understand, rules that are specified higher up in the tree cascade further down into the tree.
So I'm wondering if there's a way to make a case work where I basically have a /bands subtree that I want writeable by anyone, however there are admins and members subtrees where I want only writeable, based on special conditions.
So far, this is kinda what I have going on:
{
"rules": {
".read": "auth != null",
"bands": {
"$bandId": {
".write": "auth !== null",
"$bandId": {
".write": "auth !== null && data.child('creator_id').val() === auth.uid"
}
}
}
}
}
When I go to test "writing", in the Firebase simulator, something like /bands/-KnLeIHM4zCspwBZjZP9 where the creator_id does NOT match the specified auth.uid I have provided, I still get a simulator write success, due to the /bands tree-level having the write access.
Is there any clever way to do allow anyone to "push" to /bands but then when it gets down to the actual /bands/$bandId level, it starts looking at these various conditions? Or am I going to have to rework my data and separate out the trees into even more trees? I have other instances where this kind of thing is necessary, but this is the most succinct version I am working with that I need to solve.
Any thoughts? Thanks in advance :)
{
"rules": {
"bands": {
".read": "auth != null",
".write": "!data.exists() && auth != null",
"$bandId": {
".write": "data.child('creator_id').val() === auth.uid"
}
}
}
}
".write": "!data.exists() && auth != null" will only allow authenticated users to write to paths within bands if they don't exist (creating new content).

Resources