Update / Answer Feb 2018
It seems Query-based rules are currently unable to afford this level of security / elegance to the realtimeDB structure. Something like this would require nested sorting, variable 'key' indexes (as with the current "indexOn": ".value"
, or some other magic yet to be dreamed up by the firebase team.
In the meantime I can definitely recommend reading up on query-based rules:
- https://firebase.googleblog.com/2018/01/introducing-query-based-security-rules.html
- https://firebase.google.com/docs/database/security/securing-data#query_based_rules
Original Q: Given a list of firebase realtime-db nodes, each with a named list of groups, and a group I would like to lookup - I am looking to restrict access via query-based rules so that only nodes with the given group are returned. Everything else should be considered private data.
E.g DB:
[lookup]: {
id1: {
groups: {
randomgroup1: true
},
},
id2: {
groups: {
randomgroup1: true,
randomgroup2: true
},
}
}
Realtime DB Rules:
"lookup": {
".read": "query.orderByChild != null && query.equalTo != null",
"$uid": {
".indexOn": "groups"
}
}
And valid request/query:
const $group = 'randomgroup2';
firebase.ref('lookup').orderByChild(`groups/$group`).equalTo(true).once('value')
The above correctly returns id2: { groups: { randomgroup1: true, randomgroup2: true }}
HOWEVER the entire [lookup]
node is sent to the client to be filtered due to the lack of an index on the group names, i.e. the data is not secure.
How best to do this so to retain security? I am open to changing the structure of the nodes, or updating the security rules.
Note: this is entirely possible with the tried and tested many-to-many relationship setup (i.e. firebase brute-force duplicate databasing 101), it is similarly possible (and secure) with the technique above where only 1 group is required per record.