I have 2 questions related to firebase realtime database.
Q1) Is it possible to hide a certain node from public and only one person have access to that node ?
( I want to save a transaction key in database and only 1-2 persons can access that key from database. )
Q2) If my security rules for database are set to public, can anyone download/access complete data or they must know the structure in order to access data from database.
A1/ Yes it is possible to limit access to a certain node to a only subset of users. There are several approaches for that. If it is a small and more or less stable subset of users, you can check if their uid is contained in a specific node listing the admin users uids, as shown below:
{
"rules": {
"secretnode": {
//only an admin user can read
".read": "auth != null && root.child('adminusers/' + auth.uid).exists()"
},
"adminusers": {
".read": false,
".write": false
},
"othernodes": {
".read": true,
".write": true
}
}
}
And, for example, in the database you save the admin uids as follows:
DBRoot
- adminusers
- uid1
- name: "aaaaaa"
- otherDataItem: "xxxxxx"
- uid2
- name: "bbbbb"
- otherDataItem: "yyyy"
A2/ Yes, if your security rules for database root are set to public, "anyone (can) download/access complete data". Note that, as explained in the documentation:
Shallower security rules override rules at deeper paths. Child rules
can only grant additional privileges to what parent nodes have already
declared. They cannot revoke a read or write privilege.
In other words, this means that if your security rules for the database root are set to public anyone can download the full JSON tree representing your data, without the need to know its structure.
Related
I updateProfile with a display name. I then try to access this display name in the database security rules. But the displayName on the database is not updated.
This is using Firebase realtime DB with Flutter.
Code:
await referencedData.firebaseAuth.currentUser.updateProfile(
displayName: 'gameName' //that only the players know about
);
In my rules I have:
".write": "!data.exists() ||
auth.displayName == data.child('gamename').val()",
//rules meaning no data exists, so owner can create a new game or
//game name already set in database, I know this gamename, and it is in display name, so I can write and delete
I have spent 3 days or more searching for documentation or examples. Any ideas on where to look?
All properties are available under auth.token, and the display name is available under auth.token.name.
So:
".write": "!data.exists() ||
auth.token.name == data.child('gamename').val()",
Also see the Firebase reference documentation for auth.token.
I am using the firebase for store some users data. So now i want to delete old data with check 'last_ubdated' time < 5 min. please help for create the firebase rule for this. below is my data structure.
I have created the rule, but its not working properly.(code is below)
{ "rules": {
".read": true,
".write": true,
"$drivers":{
".indexOn": ["driverId"],
".write": "newData.exists() || data.child('last_updated').val() > (now)",
} } }
Firebase security rules can't change any data after it's been added. They only take effect at the time data is read or written by the client. If you want to arrange to delete something on a schedule, you will need another solution.
See also: Cloud Functions for Firebase trigger on time?
As Doug said, security rules can't change the data. They merely affect what (read and write) operations are allowed.
An alternative would be to use a query to only request nodes that have not expired, and then use security rules to ensure only that query is allowed. For an example of that, see my answer here: How to make data unreadable once the time indicated on its time stamp has passed?
What I am trying to do is create a firebase rule that will allow create operations if an id does not exist in allow create. To be specific, I am using firestore, not the firebase real time db. I am really new to firebase, but have done some research before posting here. Most of the examples I see are around auth.
Consider the follow data structure. The name of the collection is called flags
US - //(This is the document ID. Not auto generated
- country: United Stages
- name: US
- colors: [red, white, blue]
UK -
- country: United Kingdom
- name: UK
- colors: [red, white, blue]
What I am trying to do write a rule, IF name in the posted data does not match an existing document ID. The reason why I opted to set my own document ID is because of this article
My current rule is:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
allow read: if isLoggedIn();
allow create: if ! exists(/databases/$(database)/documents/flags/$(inComing().name))
// functions
function isLoggedIn() {
return request.auth != null
}
function inComing() {
return request.resource.data
}
}
}
But when I try posting some data with a non existent document id, I am getting an access denied error. I am logged into the app so I know it is not failing on the first part of the rule.
In summary, my questions are:
How can i check if a document ID exists based on the posted datas name key?
So what i am try is allow create: if ! exists(/databases/$(database)/documents/flags/$(inComing().name)). In the simulator, I am using create, and setting the path to flags/US. The payload is:
{"__name__":"/databases/(default)/documents/flags/US","id":"US","data":{"name":"US"}}
If I run the simulator, i get access denied which is expected. But if i change the path to flags/CA or change the payload to {"name":"CA"}, which does not exist, I am getting getting an access denied.
I am trying to secure my firebase database to allow the creation of new records, but not allow the deletion of existing records. Ultimately, I plan to utilise Firebase authentication in my app as well, and allow users to update existing records if they are the author, but I am trying to get the simple case working first.
However! No matter what I try in the database rules simulator, despite what the documentation seems to suggest, the value of data.exists() seems to always be true. From what I what I can understand from the documentation, the variable data represents a record in the database as it did before an operation took-place. That is to say, for creates, data would not exist, and for updates/deletes, data would refer to a real record that exists in the database. This does not seem to be the case, to the point where I am actually suspecting a bug in Firebase, as when setting the following rules on my database, all write operations are disallowed:
{
"rules": {
".read": true,
".write": "!data.exists()"
}
}
No matter what values I put into the simulator, be it Location or Data. I have even written a small EmberJS app to verify if the Simulator is telling the truth and it too, is denied permission for all write operations.
I really have no idea where to go from here as I am pretty much out of things to try. I tried deleting all records from my database, which lets the simulator think it can perform write operations, but my test app still gets PERMISSION_DENIED, so I don't know what's causing inconsistencies there.
Is my understanding of the predefined data variable correct? If so, why can't I write the rules I want? I have seen snippets literally trying to achieve my "create only, no-delete" rule that seem to line up with my understanding.
Last note: I am trying this in a totally new Firebase project with JUST the rules above, and only ~a few records of junk data laying around my database.
Because you have placed the !data.exists() at the root location of your database, data refers to the entire database. You will only be able to write to the database when it is completely empty.
You indicate that you run your tests with only a few records of junk data laying around my database. Those records will cause data.exists() to be true.
You can achieve your goal by placing the !data.exists() rule in your tree at the specific location where you want to require that no data already exists. This is typically done at a location with a wildcard key, as in the example you linked:
{
"rules": {
// default rules are false if not specified
"posts": {
".read": true, // everyone can read all posts
"$postId": {
// a new post can be created if it does not exist
// existing posts can only be edited by their original "author"
".write": "!data.exists() && newData.exists() || data.child('author').val() == auth.uid",
".validate": "newData.hasChildren(['title', 'author', 'timestamp'])",
}
}
}
}
The simulator allows read/write to Posts key, but the results are correct for the Users key rules. Each post under Posts has a uid value representing a user in Users key.
Are my rules wrong or is the simulator wrong? Be gentle, I'm new to Firebase. :)
Two equals:
Redacted Data view: https: // i.stack.imgur.com/GaYMj.png (remove spaces around "//")
Try changing your rules to check that a uid child exists. For example:
".read": "data.child('uid').exists() && data.child('uid').val() === auth.uid"
Based on a quick test, I think what is occuring is that when a uid child does not exist, the evaluation of data.child('uid').val() fails and is handled by assigning it a value of false. Similarly, because the user is not authenticated, auth is null and auth.uid also evaluates to false. So your rule effectively becomes ".read": "false === false", which is true.
When I first simulated a read using your rule and I did not have a uid child in my database under /posts/1, the read was granted, as you reported. When I added a uid child, it was not granted.