Here at thestartupfactory.tech we think Firebase is pretty great, and have used it as part of the stack for quite a few of our startups as well as some internal projects. Its flexibility and ease-of-use make it a quick base to build on, while its scalability means you can be happy in the knowledge that it will grow with you with very little intervention. Having said that, there are still a few gotchas which I wish I had figured out a little earlier…
1. There’s no Per-Field Access Control to a Document in Firestore
For almost any app, there will be some information that will be shared amongst other users and other information that should be private between the app and the user. As an example, say you had an app which allowed users to comment on each other’s content and showed the commenters name, but you also stored the email address and birthday of the user for the backend system to send them periodic notifications from the app and verify their age. A naive implementation of the User data in Firestore could look like the following:
If we then had a comment that referenced this user and wanted to get their name, we would access this document and pull out the name field (we are using the v9 Web Client SDK here):
But any user with access to this document would also have access to the other fields:
One way to get around this is to separate out your “public” and “private” fields into separate collections:
If this is combined with an appropriate firestore.rules file (see below), you can prevent the private fields being accessible to other users.
Now if another user tries to get any private information on a user, their request will fail, and your User’s inbox is safe from spam. 🛡✉️
2. Role Based Authorisation Should be Done Through Custom User Claims
If you want different user roles on your app, this is best implemented using Custom User Claims on Firebase Authentication Users directly, rather than relying on looking this value up in another external storage (usually Firestore). As an example on a marketplace app where users could be Sellers or Buyers, we may want to restrict it so Buyers cannot list items.
If we had stored the Buyer’s user role in their Firestore User record, we would need to add complexity to our firestore.rules to ensure that users couldn’t edit this. We would also find that it is not possible to write rules for Firebase Storage that can take the User’s role into account. Instead, we can add this role as a Custom User Claim to their Firebase Authentication User when they sign up, which prevents them changing their own Role and allows the app to reference it. With this approach, it is important that all restricted actions are made by calling a backend function that can verify the Custom User Claim to prevent any abuse. For more detailed information about this approach, check out Firebase’s documentation: https://firebase.google.com/docs/auth/admin/custom-claims.
3. The Admin SDK and Client SDK’s Types Are Not Always Consistent
When we manage times in a (Java|Type)script app at TSF, we tend to reach for Luxon, with a layer of IO-TS converting between the database representations of time and Luxon. During a recent project, we hit a snag where the converters shared between the front-end and the backend were erroring in one and not the other. After drilling into the issue, we found that the type of a value representing a Timestamp in Firestore is different between the front-end and the back-end see issue here, and we needed to write a separate codec for each environment, including it alongside our shared codecs.
By way of a code example for an app that can schedule meetings, using a Meeting object, as retrieved from firestore and what we would like in our app:
We then end up with a project structure like so:
And in each of these files:
Structuring things like this does lead to some duplication, but you will now have type-safe codecs on both the front and back end that behave as expected. 🎉
Hopefully these tips will also speed you along in your Firebase journey and help avoid some pitfalls! If you are kicking off a new venture and are not sure about the technology to use, just need some guidance, or if you have a burning business idea you need some tech built for, just get in touch.