owned this note
owned this note
Published
Linked with GitHub
---
tags: mstu5013
---
# firebase authorization
###### refer to official firebase security rule documentation here:
https://firebase.google.com/docs/database/security/
## authorization
Firebase Database Rules allow you to control access for each user. For example, here's a set of security rules that allows anyone to read the path /foo/, but no one to write to it:
```javascript=
{
"rules": {
"foo": {
".read": true,
".write": false
}
}
}
```
.read and .write rules cascade, so this ruleset grants read access to any data at path /foo/ as well as any deeper paths such as /foo/bar/baz. Note that .read and .write rules shallower in the database override deeper rules, so read access to /foo/bar/baz would still be granted in this example even if a rule at the path /foo/bar/baz evaluated to false.
The Firebase Database Rules include built-in variables and function. Here's an example of a rule that grants write access for authenticated users to /users/<uid>/, where <uid> is the ID of the user obtained through Firebase Authentication.
```javascript=
{
"rules": {
"users": {
"$uid": {
".write": "$uid === auth.uid"
}
}
}
}
```
Data validation
The Firebase Realtime Database is schemaless. This makes it easy to change things as you develop, but once your app is ready to distribute, it's important for data to stay consistent. The rules language includes a .validate rule which allows you to apply validation logic using the same expressions used for .read and .write rules. The only difference is that validation rules do not cascade, so all relevant validation rules must evaluate to true in order for the write to be allowed.
```javascript=
{
"rules": {
"foo": {
".validate": "newData.isString() && newData.val().length < 100"
}
}
}
```
## simple rules review
now, let's consider some super simple rules for our site:
```javascript==
/* no security requirement */
{
"rules":{
".read": true,
".write": true
}
}
/* no one can access */
{
"rules":{
".read": false,
".write": false
}
}
/* google authenticated users only */
{
"rules":{
".read": "auth != null",
".write": "auth != null"
}
}
```
It's a good start, but we can do better to talor our own data structure, which now looks like this:
![](https://i.imgur.com/1lmcDhI.png)
Translating from our site data structure, we can probably start from this rule:
```javascript=
{
"rules": {
"memes": {
"public": {
".read": true,
"$memeID": {
".write": "auth.uid === $userID",
}
},
"private": {
"$userID": {
".read": "auth.uid === $userID",
".write": "auth.uid === $userID",
"$memeID": {
}
}
}
}
}
}
```
1. we essentially translate our data structure into a json file.
2. we simply use variable $ to define userID and memeID, because they are dynamically decided when user sign in and when data is written into firebase. the actual names don't really matter, we can call them anything we want.
3. we allow anyone to read public data, anyone whose auth.id(google authenticated id)matches with what's on the record in the database to write at a particular private user's data field. If google says you are user ABCDEFG, great, you can change what's in the database under node ABCDEFG.
Problem, we never pushed userID to public comment nodes, but only inside each message.
Admin_entry.tag, line 43
```javascript==
let updates = {};
this.toggle = function () {
this.myMeme.public = !this.myMeme.public;
updates['private/' + this.myMeme.userID + '/' + this.myMeme.id] = this.myMeme;
if (this.myMeme.public) {
// console.log("this.myMeme".this.myMeme);
updates['public/' + this.myMeme.id] = this.myMeme;
} else {
updates['public/' + this.myMeme.id] = null;
}
// console.log("this.myMeme", this.myMeme);
// console.log("updates", updates);
messagesRef.update(updates);
}
```
No worries, we can dig into child level with firebase security rules!
```javascript=
/* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */
{
"rules": {
"memes": {
"public": {
".read": true,
"$memeID": {
".write": "data.child('userID').val() === auth.uid"
}
},
"private": {
"$userID": {
".read": "auth.uid === $userID",
".write": "auth.uid === $userID",
"$memeID": {
}
}
}
}
}
}
```
We are almost there! However, if you push this security rule to your site, you will get a validation error when you try to publish private messages. This is because before a private data gets published, there is ==NOTHING== inside the public node, therefore the ==data.child('userID').val()== attribute has no value and cannot be verified against google authentication data record ==auth.uid==.
No worries, we can update it to the following:
```javascript=
{
"rules": {
"memes": {
"public": {
".read": true,
"$memeID": {
/* ".write": "data.child('userID').val() === auth.uid", */
".write": "!data.exists() || data.exists() && data.child('userID').val() === auth.uid",
".validate": "newData.child('userID').val() === auth.uid"
}
},
"private": {
"$userID": {
".read": "auth.uid === $userID",
".write": "auth.uid === $userID",
"$memeID": {
".validate": "newData.child('userID').val() === auth.uid"
}
}
}
}
}
}
```
In line 8, we say allow write if data never existed. or if someone already published there, then go ahead with the user id match rule.
Lastly, we also add validation rule for both new data written in public and private, to ensure userID matches google authentication record before allowing data to be pushed to our backend database.