Security rules
Learning objectives
- You know how to create security rules in Firebase.
Right now, even though we have restricted the notes to be specific for specific users on the client side, anyone can still access the database and modify the data, as client-side verifications and functionality is easy to bypass. To prevent this, we can add security rules to the database that govern access to the data. When working with Firebase, we use Firebase Security Rules.
The security rules can be accessed in the Firebase console under Firestore Database
at the tab Rules
. The rules are written in a custom language called Firestore Security Rules
, and are evaluated on the server -- clients are only allowed to read and write data that is allowed by the rules. By default, as we started with the test database when creating the database, the rules are set to allow anyone to read and write database content, given that the time of the request is within the given boundaries. As an example, the following rules allow anyone to read and write data to the database, as long as the request is made before May 1st, 2023:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if
request.time < timestamp.date(2023, 5, 1);
}
}
}
In our case, we wish to restrict access to the notes so that only the user who owns the notes can read the notes. That is, the user whose user id is the same as the userId
field of the note should have access to specific notes. To do this, we still continue monitoring the cloud firestore database, as follows.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
}
}
But add additional restrictions on the database path /notes
for the specific notes.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /notes/{noteId} {
}
}
}
Now, all the database requests that are made to the path /notes
will be evaluated by the rules that we specify. The rules can use both information from the request -- such as user id (in request.auth.uid
) and information from the database -- such as the userId of a specific note (in resource.data.userId
). Granting access to a specific note is done by allowing access to the said resource, if it matches specific rules. Below, we grant the user the access to read and delete notes that they own.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /notes/{noteId} {
allow read, delete: if request.auth != null && request.auth.uid == resource.data.userId;
}
}
}
The above security rule works already quite well, but we cannot presently create new notes. To accommodate for this, we'll add another rule that allows creation only if the data in the request contains a userId
field that matches the user id of the user making the request. With this modification, the rules would be as follows.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /notes/{noteId} {
allow read, delete: if request.auth != null && request.auth.uid == resource.data.userId;
allow create: if request.auth != null && request.auth.uid == request.resource.data.userId;
}
}
}
Save the above rule to the database, and try it out.
Now, authenticated users can create notes if the
userId
field in the request matches the user id of the user making the request. Similarly, the authenticated user can read and delete notes that they own.