Let’s say for instance a user writes about an event to the Firebase database, what the user writes has a time stamp attached to it and other users are able to read what was written in a list view using the FirebaseListAdapter. Is there a way to make the data written by the user unreadable once the time on the time stamp has passed?
-
Wow, thank you, I will try it – Bwalya Aug 08 '19 at 11:30
1 Answers
There's a big difference here between whether you have a single item, or a list of items.
Securing access to a single node
If you have a single node like this in your database:
"content": {
"expiresAt": 1565275079920,
"content": "This content is only readable until Thu Aug 08 2019 07:37:59 GMT-0700"
}
You can ensure this node is only readable until its expiry timestamp with these rules:
{
"rules": {
"content": {
".read": "data.child('expiresAt').val() < now"
}
}
}
When somebody attaches a listener to /content
up until the expiry timestamp it will be allowed, after that any new listeners will be rejected.
Securing access to a list of nodes
But things get more complicated when you have a list of data as:
- You can only read/query data if you have read access to all that data.
- Once you have read access to a node, you have read access to all data under that node.
Combined these two fact mean that security rules cannot be used to filter data.
So if you have a list of these nodes above:
"content": {
"-Ldshdh13...": {
"expiresAt": 1565275079920,
"content": "This content is only readable until Thu Aug 08 2019 07:37:59 GMT-0700"
},
"-Ldshdh13...": {
"expiresAt": 1565277079920,
"content": "This content is only readable until Thu Aug 08 2019 08:11:19 GMT-0700"
},
...
}
In order to be able to query this data, the user must have read permission on /content
. And as soon as they have full read permission on /content
, you can't keep them from reading certain nodes under there.
The only way to make this scenario work is to use a combination of a query and a security rule that validates this query.
Step 1: query for only the data that you're allowed to read
So if you should only be able to read data that expires in the future:
var ref = firebase.database().ref('content');
ref.orderByChild('expiresAt').startAt(Date.now()).once('value',...
Step 2: use security rules to only allow reads with this query
The security rules will now check whether the user is passing the correct orderBy
and value in to their query so that they're only accessing non-expired data:
{
"rules": {
"content": {
".read": "query.orderByChild == 'expiresAt' &&
query.startAt >= now"
}
}
}
A few things still to note:
- The security are applied when the listener is attached. So the value of
now
is only checked at that moment, it doesn't get modified in any way after that. This is usually not a security problem, but means you will need to remove outdated data in the application code too after attaching the listener. - You may need to tweak the rule a bit, as the
Date.now()
in the client and thenow
in the rules may not be exactly the same. Adding a few seconds in the security rule may be a good idea.
For further reading, I highly recommend:
- documentation on the fact that permissions cascade
- documentation on rules-are-not-filters
- previous questions on rules are not filters. Note that many of these probably predate the introduction of query-based security rules.
- documentation on query based security rules

- 565,676
- 79
- 828
- 807
-
sorry to disturb you in anyway, but I am kindly asking if you could show me how to do the code. 'var ref = firebase.database().ref('content'); ref.orderByChild('expiresAt').startAt(Date.now()).once(...... ' in Java – Bwalya Oct 08 '19 at 17:31
-
The Firebase API is fairly consistent across platforms. Since you didn't tag your question with any language, I answered in JavaScript because it's typically most concise. If you're having a hard time implementing this in Java, edit your question to show what you tried (or post a new question) and somebody may be able to help. – Frank van Puffelen Oct 08 '19 at 19:10
-
Alright, thank you, I will try that, I actually tried searching the documentation under query but I couldn't find any examples in java or with .'once('value...' – Bwalya Oct 08 '19 at 19:20
-
Check the documentation for Android [reading data once](https://firebase.google.com/docs/database/android/read-and-write#read_data_once). – Frank van Puffelen Oct 08 '19 at 19:29