What’s up guys, Eze is here. I already did couple of posts about Firebase and how to use the Real-Time database and the storage with AngularJs in case you missed it you can check here. Today I want to talk about security rules. I’ve answered this question in StackOverflow and that motivated me to write this post.
Understanding Rules object
As almost everything in Firebase the rules for our database will be a JSON Object. We are going to use this object to define security, data structure and of course validations. As you can see below the structure of this object is quite simple. It has only one property called rules which will have the rules definitions.
{
"rules": {
"users": {
".read": "root.child(‘access_token’).child(auth.uid).exists()"
}
}
}
Rules types
Under the security rules we can define four different types. We can apply those types to the complete database as is in the example above or we can define every type at an specific path.
- .read: This rule is a type of Security Rule which grants a client read access to a database location.
- .write: This rule is a type of Security Rule which grants a client write access to a database location
- .validate: This rule is used once a
.write
rule has granted access, to ensure that the data being written conforms to a specific standard - indexOf: This rule tells the database servers to index specific keys in your data to improve the performance of your queries
Rules variables
As you can imagine Firebase use an specific set of variables to perform the rule types that we defined before.
- auth: This variable will contain the token payload in case the is an authenticated user.
- provider : The authentication method used by the user.
- uid: This will be the uid to the authenticated user.
- token: This variable contains the contents of the Firebase Auth ID token.
- $location: In this case the $ is used to reference in a generic way to the child within the path.
- now: Contains the number of milliseconds since the Unix epoch according to the database servers.
- root: It’s a RuleDataSnapshot to the current data at the root level. That means we can query others path to validate.
- data: It’s a RuleDataSnapshot corresponding to the actual data in the path.
- newData: It’s a RuleDataSnapshot corresponding with the data that will result if the write is allowed.
Rules methods and operators
To complete the types and variables Firebase offers us a series of method to apply over the variables that we will use within the types. Just to name a couple we can use the val() method to retrieve the value of the snapshot o child() to query the paths.
In the same way we can use most of the logical operators like === equals , !=== not equals, || or, ! not and so on.
Using all together
In the example below I defined a rule for the path users. Using the $user means that this rule is for every child under the path users with the id user. Then I defined the types so I started with .read, by assigned true means that everyone (even unauthenticated users) can read under this path. For .write path I access to the variable root to query the access_token path with a child that belongs to the authenticated user uid and then use the method exists to validate if there is data under this path. To finish I used the .validate type to validate the newData to write has the right structure.
</span><span class="pun">{
"rules": {
"users": {
"$user": {
".read": true,
".write": "root.child('access_token').child(auth.uid).exists()",
".validate": "newData.hasChildren(['name', 'age'])"
}
}
}
}
For a complete reference of Firebase use this link.
If you found this post useful please don’t forget to press the like button and share it. If you are in doubt don’t hesitate to ask a question and, as always, thank you for reading.