Pass context value into firestore document add/set/update from Admin SDK - firebase

I am looking to use the https.onCall to accept some input from a user (such as data about another user). I'd then like to do some advanced processing on that data including retrieving sensitive data from other entries on my firestore that should not be exposed. Depending on the outcome of that analysis, I will update other locations in the database. However, I am concerned about the security of the original call and its source. I know that I have the context parameter on the onCall to verify the source was logged in, but I'd like to apply security rules to the final write based on the context.auth provided to the cloud function.
The security rules are straight forward for normal database operations but not if I'm doing an operation (seeded by a normal user) routed through the Admin SDK.
Thoughts?

but I'd like to apply security rules to the final write based on the context.auth provided to the cloud function
As you are aware that you can identify which user made a call to functions as well as that Admin SDK has super-access to database, the general flow should be to write functions in a way that they only edit documents that should be editable by the user.
If you had still like to narrow down access, you can do that for firebase database by passing databaseAuthVariableOverride when initializing admin app.
Read more on authenticating with limited privileges

When you use the admin SDK, or any of the server SDKs, it always bypasses all security rules. Rules only apply to access coming directly from web and mobile clients using the client SDKs.
If you need to apply some sort or restricts to data written from your backend, you will need to code that into the logic of your backend code. Security rules will be of no help.

Related

How to block firestore REST API access

I have a flutter app and use firebase auth and firestore. The data in firestore is only read and written from within the app.
I just realized, that every authorized user can access his data in firestore via the REST apis, if he has a correct auth token (e.g. from the AUTH rest api) and the API_KEY. As I understand, the API_KEY is not private.
So, even if I set up my security rules correctly, so that a user can only read and write his data, he could still access and change the data via the REST API. This could break my data model, as the data has to be structured in a special way.
Is there any way to allow access to firestore only from within the app and block it from REST calls?
Why are firebase API keys default unrestricted?
Should I limit the key to be used only by the Android APP like described here?
You should be validating the data requests within Security Rules to ensure that your data structure is being adhered to in all cases.
https://firebase.google.com/docs/rules/data-validation
as for the Rest API, it is not possible to outwardly block or deny it as it is built into GCP's core as part of the public API, however, you may be interested in App Check which can deny requests from outside your Android/iOS/Web app
https://firebase.google.com/docs/app-check
it's in early Beta and can help with unsolicited abuse to the mentioned platforms.

Securely setting the first custom claim on a Firebase user

What is the standard, secure way to set the first custom claim on all Firebase users?
Firebase provides some great documentation and examples for understanding and using custom claims -- e.g. this great video example -- but most examples use an existing custom claim to authorize the creation of other custom claims; and as of this post the Firebase console provides no way to set/edit/view custom claims, nor can custom claims be set via the CLI.
Here are some options I am considering:
Create a distinct admin project, which can be used by a service account to create custom claims via the Firebase Admin SDK.
Use a Cloud Function to perform custom claim creation iff a certain Firebase console action is taken, e.g. creating a Firestore Document in collection inaccessible via security rules.
Ignore security for the creation of the first custom claim; only add security after this is already a custom claim on a Firebase user.
Have you encountered this problem and solved it more-elegantly?
There is no real standard way to set Custom Claims. The only constraint, as you know, is that they can only be set from a privileged server environment by the Firebase Admin SDK, i.e. from one of your servers, or, easier and more serverless-oriented, via a Cloud Function.
So, within this constraint, you can do whatever you want. The first two options in your question are totally valid and good ones, IMO. I've wrote an article about a year ago (How to create an Admin module for managing Firebase users access and roles) in which we use a Callable Cloud Function to do the job. Today, in most of my projects, I prefer to use a Firestore collection which triggers the Cloud Function, but it is more or less equivalent (the Callable Cloud function in the article actually creates a Firestore doc).
In this article, I share a simple approach for creating the first Claim (which I call the Admin user Claim): use a temporary Cloud Function that you trigger by creating a doc in a temporary, secured, Firestore collection. Not a very elaborated and elegant method, but it does the job...
About your third option ("Ignore security for the creation of the first custom claim") I don't think you need and should do that.
You can do as described in the article and above. In a nutshell:
Set up your system with access rights restricted to the user with the Admin Custom claim (e.g. a security rule to create a doc in the dedicated Firestore collection, or a check in a Callable Cloud Function that the caller has the Admin Claim)
Create the Admin user in the Auth service
Assign him the Admin user Claim via the method detailed above.
You are done and no security hole.
Finally, it's worth noting that a new experimental Extension dedicated to setting claims with Firestore was launched in January this year. See here and here.

Your Cloud Firestore database has insecure rules - flutter firebase db

I developed a flutter app,
I use Firebase as my DB, which means that any user can write and read from my DB,
I'm getting the following email every couple of hours.
[Firebase] Your Cloud Firestore database has insecure rules
We've detected the following issue(s) with your security rules:
any user can read your entire database
any user can write to your entire database
Which is exactly what I want, since I want my app to be available to unregistered users.
Did I missed something? is my app is actually insecure?
The access to the DB is done through the app with filters only user specific data.
Is there a way to make my more secure, and keeping it available for unregistered users?
I also not sure why allowing only registered user will make it insecure, since any one can register to the app with a click of a button.
Please shed some light on this issue.
You will definitely need to learn how to use security rules. A full discussion is beyond the scope of a single answer, but you should know that security rules allow you to specify who (signed in through Firebase Auth) can read and write which documents and collections. Not using security rules at all is a massive security hole.
The video in the following documentation explain it in a very simple way
https://firebase.google.com/docs/firestore/security/get-started#writing_rules
The bottom line is that you must auth your users, and then use security rules for filtering the data, inorder for your data to be secured.
Using insecure rule should be done only for testing s

Restricting read/write to firestore based on android package name

I have a Firebase project which contains 3 different android applications. These 3 applications utilize the same data stored under Cloud Firestore. My problem is that some of the data is particular to a single app only while some documents contain data which is supposed to be read by two of the three apps. I need to write Firestore security rules to implement this.
Is it possible to restrict read/writes to a particular document based on the android package name without having to explicitly send data regarding the app-id in each request?
Is there anything else which can be used instead of the package name to uniquely identify the applications while adding firestore security rules?
So far I have been trying to restrict read and writes based on the kind of authentication used by the apps as one app uses only phone auth while the other uses both email and phone linked together. So if the email is missing but the phone is present, I know it's from the first app. Is there any better way to do it?
It's not possible exactly as you're describing. Security rules don't have any way of determining or limiting the origin of access. They just limit who can read and write what data, as determined by Firebase Authentication.
You can use the authentication provider of the signed-in user via request.auth.firebase.sign_in_provider, or any of the other per-user properties shown in the linked documentation. You can also use custom claims in request.auth.token to tag users with some privilege that allows their access to some data, which must be set using the Firebase Admin SDK on your backend.

Hashing algorithm support in firebase real-time database security rules

I would like to compute hash functions inside security rules.
md5hash(auth.token.email) === $hashedvalue
Is there a way for me to do that in bolt? or natively in firebase real-time database?
Use Case:
Basically I would like to store the email as the key in the firebase real-time database and use it in the firebase security rules for authentication and authorization. Since few special characters like dots (.) are not supported in keys I was thinking of using some hashing algorithm which is available in firebase real-time database.
auth.id doesn't work in my case as I'm not giving any sign up option as I have a pre defined set of users with pre-defined profile details accessing my application through their Google login (which I know the email ID of) to start with and since they haven't yet logged into my application I don't have a corresponding ID to authenticate or authorize them on their first attempt.
This page of documentation shows all the functions available in Realtime Database security rules. There are no hashing functions there. You could file a feature request to explain you use case.
For the sake of posterity, I got this working with a small workaround (Yay!).
From the fire firebase real-time database documentation I found out that firebase security rules supports an amazing string function called "replace" xD.
So now I pre process the email Ids by replacing all the characters not supported as database key with their url encoding equivalent before creating the key and use the same set of replacements in my firebase security rules.

Resources