Writing rules for Google Cloud Firestore - My frustrations and how I managed it
Have you ever worked with GCF - Google Cloud Firestore and decided it is time to go live with your mobile app or your website but then Google notifies you that client access to your cloud firestore is not secure or that it will soon expire due to the time limit google provides for the testing phase during which you are not mandated to set security rules?
At that time I always try to bypass this warning by extending the time limit and changing the version, which is like me saying; hey GCF, give me one more month, I will try to read up on how to write security rules before then and I will definitely set it up.
One more month, I find myself extending again and again.
What is the cost of not setting security rules?
This could be very disastrous to your early startup or that wonderful project you hope to scale; you are opening the door wide for public access to all of the sensitive data in your domain.
I thought about this and the fact that am taking my app from the development to publishing phase. That procrastination to read up and understanding Security rules had to stop. I had to face it before what I fear the most hit me hard.
Setting security rules for your cloud storage is very essential and after studying it from the official documentation, I realised how simple it could be, as simple as saying, this document reference should be accessible to some user roles and that some users can perform certain operations.
here are some examples:
rules_version = '2'; - the version number for my rule
service cloud.firestore {
match /databases/{database}/documents {
match/users/{userId}{
allow read: if isLoggedIn() || isValid(userId) || isAdmin();
allow create: if isPartialUser();
allow update: if isLoggedIn() && (isValidUser() || isAdmin());
allow delete: if isAdmin();
}
* other match here*
...function definition here...
}
the above is a typical example picked from a deployed app rule. here is a major break down and by the time I explain it all, you will feel the urgency to begin setting rules for your cloud firestore if you have not begun doing so.
match users/{userId}: this is a document ref where users is a collection and userId matches any doc Id which we define the following privilege for.
the match keyword simply works like your regular expression; saying - hey Bob for the collection users and for the userId doc ref, perform the following operation
allow read: if isLoggedIn() || isValid(userId) || isAdmin();
to allow read just as the name sounds simply means to allow the role to read the collection ref as defined in the match. this is like saying - hey Bob, if there is a user who isLoggedIn or the user isValid user or the user who logged in isAdmin then allow that role to read our match.
That's it, yes, as simple as that.
allow create: if isPartialUser();
to create means to modify, when someone is given the privilege to create it means he can add a new collection, document or field in your cloud firestore. you want to think about this; for the use case we are saying is the user is a partial user then he is allowed to create the document in our match.
allow update: if isLoggedIn() && (isValidUser() || isAdmin());
function isLoggedIn(){
return request.auth!=null && request.auth.token.email_verified;
}
the above basically defines the condition that meets been loggedIn. That is, if the request auth property is not null and the email has been verified, hence the user is LoggedIn. you might decide how you want to define isLoggedIn depending on the use case of your project.
function isValid(userId){
return request.auth.token.email == userId;
}
the above says the userId is valid if the email used in registration is equal to the userId. In this case, a user logged in successfully has access to his own specific document and not other users document.
function isPartialUser(){
return request.auth!=null || !request.auth.token.email_verified;
}
As a partial user, that is a user who has authenticated or his email has not been verified. In the use case, the app wants the user to be able to sign in after sign up without having to verify his account from his email yet maybe because he could just browse some products or items and decide if he is ready to explore other functionalities then, in this case, he will be asked to verify his account or rather request a verification mail sent to his mail when the need arises within the app.
function isValidUser(){
return request.auth.token.email == request.resource.data.email;
}
the above states that if the auth email is the same as the resource data email; the resource data email is the email among the users registered in the app, then they are eligible to update the fields in the document reference. This is valid such that if a user is logged in and his email is among those in the resource for the app, then he can update his fields. It simply states that as an authenticated user, update the record that pertains to you as a user.
function isAdmin(){
return request.auth.token.email == 'aparticularadminemail@admin.com';
}
here we are saying if the email been authenticated is equal to the particular email specified, then he is an Admin and the operations defined for this admin is carried out by the admin successfully.
feel free to connect with me for more insight on security rules for google cloud firestore or to help with yours too.
Comments
Post a Comment