Allow user to read only own content with firebase rules? - firebase

I'm trying to set users to get only own objects. I have a tasks which have 3 attributes on fb-database: task-text, datetime, user. user have user uid. I want to write a rule that allow user to read only own tasks.
So far I have this and it dont work:
{
"rules": {
"tasks": {
".read": "auth.uid == data.child('user').val()",
".write": "auth.uid != null",
}
}
}

You'll want to break up the tasks by user, so you'll have a structure that looks like:
root
tasks
Puf
...
Andrew
...
James
...
This can be secured via rules that look like:
{
"rules": {
"tasks": {
"$userId": {
".read": "auth.uid == $userId",
".write": "auth.uid == $userId",
}
}
}
}

Related

Firebase Realtime Database Rule

My database rules is as below which only lets authorized users to read/write their own data. However, I want everyone to read all database without any authorization. How can I do it?
{
"rules": {
"posts": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
It is not 100% clear what you mean by "I want everyone to read all database without any authorization".
If you mean that anyone should be able to read the posts (even users without an account, i.e. unauthenticated users) you would adapt your rules as follows:
{
"rules": {
"posts": {
"$uid": {
".read": true,
".write": "$uid === auth.uid"
}
}
}
}
If you mean that only authenticated users should be able to read the posts of all the other users (in others words, authenticated users shall get the authorization to read all posts), you would adapt your rules as follows:
{
"rules": {
"posts": {
"$uid": {
".read": auth != null,
".write": "$uid === auth.uid"
}
}
}
}
See the doc for more details.

Firebase Rules to let users see their own data, ERROR Listener at /jobs failed: permission_denied

I am trying to figure out Firebase Rules that will allow my users to only see their data in their App.
Currently this is my Realtime Database File:
and this is my Firebase Set Rules:
{
"rules": {
"users": {
"$uid": {
".read": "auth.uid === $uid"
}
},
"jobs": {
"$uid": {
".read": "auth.uid === $uid"
}
}
}
}
How do i change the rules to be able to let users see their data that is relevant to their userid?
It looks like you're using the user's UID as the key for their data in both jobs and users. In that case, you can ensure that each user can only read their own job and profile with:
{
"rules": {
"users": {
"$uid": {
".read": "auth.uid === $uid"
}
},
"jobs": {
"$uid": {
".read": "auth.uid === $uid"
}
}
}
}
Note that this is almost a literal copy of the sample in the Firebase documentation on securing user data.

How indexOn works in firebase-database?

My database looks like the following:
"users": {
"2387653478": {
"score": 1000,
...
},
"8456756547": {
"score": 2000,
...
},
...
}
I want to do a simple ranking sorting by "score" but I have many users and I should add an indexOn in the rules to optimize:
"rules": {
"users": {
"$user": {
".read": "auth != null",
".write": "auth != null && auth.token.firebase.identities['facebook.com'][0] === $user",
".indexOn": ["score"]
}
}
}
Is the optimization 100% functional just when adding the indexOn in rules?
What about the users created before adding the indexOn?
Thanks in advance!
When you update your rules file (either through the Firebase Database console or through the CLI), the Firebase Database (re)creates all the indexes defined in the rules. It does this for all existing data and then continues to update those indexes for any data changes.
But you've defined the index on the wrong level. You want to allow querying of the users node on the individual user's scores. So you have to define the index on users:
"rules": {
"users": {
".read": "auth != null",
".indexOn": ["score"]
"$user": {
".write": "auth != null && auth.token.firebase.identities['facebook.com'][0] === $user",
}
}
}
You'll notice that I also moved your .read rule up to users. Because without that, you would not have read permission on /users and thus can't query it.

Firebase Database Rules

I'm having some issues wrapping my head around the database rules and the documentation isn't helping. I am trying to set things up so that only the user can delete their own items, however at the moment I'm getting permission_denied errors. I am assuming that it is because I don't have a read/write rule on the 'items' level. However I feel that if I just added a 'auth != null' rule it would give to much permission. Any thoughts?
the database setup:
users:
{
user_1 {
items:
{
item_1: true,
item_2: true,
}
},
user_2 {...},
etc {...},
},
items:
{
item_1
{
user: "user_1"
....
},
item_2
{
user: "user_1"
....
},
}
The database rules look like
{
"rules": {
"users": {
"$uid":{
".read": "auth != null && auth.uid==$uid",
".write": "auth != null && auth.uid==$uid"
}
},
"items": {
"$itemID": {
".read": "root.child('Users/'+auth.uid+'/'+$itemID).exists()",
".write": "root.child('Users/'+auth.uid+'/'+$itemID).exists()"
}
}
}
}
At the moment any user can delete any item.
To ensure that only the owner can delete the item, you need to not just verify that:
"items": {
"$itemID": {
".read": "auth.uid == data.child('user').val()",
".write": "auth.uid == data.child('user').val()"
}
}
There is no need to check if they exist in the /users node as far as I can tell, although you can easily add that back if needed.
But if a user can only read/write their own items, I'd model the data differently:
"items": {
"$uid": {
".read": "auth.uid == $uid",
".write": "auth.uid == $uid"
"$itemID": {
}
}
}
This is much simpler to model and will give you much better scalability, since the database only ever has to consider the data for one user.

Firebase rule to only allow deletion of old data by any authenticated user

The question is about the ships branch expanded below. Everywhere only authenticated users are allowed to write their OWN data everywhere. However, there is one exception. ANY authenticated user may read data out of the ships branch.
So far I had no trouble but here is one special rule:
ANY authenticated user may delete a child under any uid in the ships branch provided that the timestamp is 10 seconds or older.
I want any user to be able to call:
firebase.database().ref('/ships/gp3tJa3tgThukt39EejqJpZq12L2/granit').remove();
uid: gp3tJa3tgThukt39EejqJpZq12L2
shipid: granit
And be granted the rights to delete only.
In order to check the age of the record I store a firebase.database.ServerValue.TIMESTAMP in the perf array at index 0 (I am using an array here because this record is frequently updated and I want to keep data to a minimum).
On the client side, the program can see when a record is likely to have expired and only then call remove. This in order to avoid wasteful failed calls.
I need some help to define the correct rule. The line in question is highlighted in the second example where I attempted to define this rule.
{
"ships": {
"EnBawzb0CjZVgAKrMZD4HE3k5rW2": {
"oasisoftheseas": {
"param": {
"scale": 0.33075936163570846,
"type": "cruise/royalcaribbean/oasisoftheseas"
},
"perf": {
"0": 1,
"1": 1.11014724E7,
"2": 1.70473256E7,
"3": 115.7,
"timeStamp": 1475144447302
}
}
},
"gp3tJa3tgThukt39EejqJpZq12L2": {
"granit": {
"param": {
"scale": 0.12235531736978282,
"type": "riverbarge/granit"
},
"perf": {
"0": 5,
"1": 2.05622392E7,
"2": 13154087,
"3": 285.9,
"timeStamp": 1475144450086
}
}
}
}
}
Below the rules. It is the write rule for $shipid that I am interested in defining correctly.
{
"rules": {
"anchors": {
"$uid":{
".read": "auth.uid === $uid",
".write": "auth.uid === $uid"
}
},
"completed": {
"$uid":{
".read": "auth.uid === $uid",
".write": "auth.uid == $uid"
}
},
"ships": {
".read": "auth !== null",
"$uid":{
".write": "auth.uid === $uid",
"$shipid":{
".write": "((auth !== null) &&
(now - data.child('perf').child('timeStamp').val() >= 10000))"
}
}
},
"shipslog": {
"$uid":{
".read": "auth.uid === $uid",
".write": "auth.uid === $uid"
}
}
}
}
Well, I figured it out as confirmed by Frank. The solution edited in the question is correct, secure and working.
"ships": {
".read": "auth !== null",
"$uid":{
".write": "auth.uid === $uid",
"$shipid":{
".write": "((auth !== null) &&
(now - data.child('perf').child('timeStamp').val() >= 10000))"
}
}
},...
Any data can be written to the ships branch by the owner of the record. At a deeper level I use the uid wildcard and shipid wildcard to get to the data that can expire and needs to be removed.
The timestamp is secure as it is provided by the server on the server side. Deleting a ship can only happen by any authenticated user AND provided the difference between now and the timestamp is greater then 10000 milliseconds.
This is probably a nice clean generic way to let client apps cleanup old data without the need for serverside business logic.

Resources