firestore security rules for server side requests - firebase

i'm flutter-fire user since last fall
Note: The server client libraries bypass all Cloud Firestore Security
Rules and instead authenticate through Google Application Default
Credentials. If you are using the server client libraries or the REST
or RPC APIs, make sure to set up Identity and Access Management (IAM)
for Cloud Firestore.
Comment above is from link by firebase team. It sounds like 'server client libraries' or apis in the comment mean the requests from outside of my mobile apps, and they gon bypassing cloud firestore security rules. But when i tried the same get request with Postman with just same request from the one in my app without permission, the response in Postman console was fine, which means that there came a permission denied error.
So, here comes my question. I hope to know what types of requests exactly are equivalent to these 'server client libraries' or 'the REST or RPC APIs' mentioned in the official reference that bypass all the security rules. Postman is exactly 'the REST', and firebase worked as i wanted(produced permission denial) perfectly in this case. So there must be some specific types that firebase team actually intended to refer to be careful of.
I understand that firebase-admin sdk is one of the possible server side libraries, but exactly the same permission or auth procedures should be required when we tried to access firebase admin sdk which can control firebase data above the security rules just like firebase team commented. So the question is focusing on possible attackers' solutions to maliciously manipulate our firebase without the proper security procedures.
Hope some firebase gurus would give cool answers for the question with awesome knowledge and experiences! Thank you in advance [:

As their name indicate, the server client libraries are to be used from a server or from a "trusted environment" like Cloud Functions.
When interacting from your server (or your trusted environment) with the Firebase server APIs you don't authenticate as you would authenticate from a client application. Instead of using user accounts created through the Firebase Authentication service (e.g. email/password account) your server should use Google service accounts. More details here in the Firebase doc.
Note that for Cloud Functions, you initialize the Admin SDK with no parameters. In this case, the SDK uses Google Application Default Credentials (exactly as indicated in the documentation excerpt you mentioned in your question).
So, when your server (or your Cloud Function) interacts with the Firebase server APIs, since it is authenticated with a service account, the requests bypass all Cloud Firestore Security Rules. In other words, if you want to implement some check to allow/forbid specific operations based on specific parameters/values, you have to implement them in your code.
For the REST API, it is the same. The REST API can be used from a client application (a web app, a Flutter app, ...) or from a server.
Depending if it is a client or a server, you should authenticate by using a Firebase Authentication ID token or a service account (together with Google Identity OAuth 2.0 token), as explained in detail in the documentation.
So, when you make a request to the API with Postman without permission, as you did, the API detects that there is no Google Identity OAuth 2.0 token or Firebase Authentication ID token associated with the request and then the Security Rules are enforced => you get a "permission denied error".
In conclusion, if you correctly define your Security Rules you should not encounter any problem with "attackers maliciously manipulating" your database.
Note however that Security Rules only based on auth != null may not be sufficient to protect your data, as explained in this answer.

Related

Using Firebase Security Rules from a web server

Do any of the Firebase Node/JS SDKs support making calls to Firestore from a node server or cloud functions (e.g. nextjs, remix) on a users behalf, respecting security rules for the authenticated user and supporting sessions for multiple simultaneous users?
Use case:
I have a mobile application with Firebase Security rules set up. I want to serve the same data from a server side web application without reimplementing the Firebase security rules on the web server and keeping them in sync.
e.g. if a user requests a post by id, and Firebase rules prevents them from having access to that specific post, I want Firebase to tell me that and for the web server to forward the 403 status to the user.
More info:
I read this:
If you are developing a Web or Node.js application that accesses Cloud Firestore on behalf of end users, use the firebase Client SDK.
Which suggests this should be possible, however my understanding is that:
firebase-js-sdk can only have one user authenticated at a time so would not be safe if handling async calls from multiple users at once
firebase-admin can be run as a specific user, but this can only be done during initializeAdminApp and again would affect all requests that are currently using the firebase-admin import
Is that correct? Are there any other ways to act on behalf of the authenticated user from a web app?
The only thing I can think of would be the REST API…
https://firebase.google.com/docs/firestore/use-rest-api
Do any of the Firebase Node/JS SDKs support making calls to Firestore from a node server or cloud functions (e.g. nextjs, remix) on a users behalf, respecting security rules for the authenticated user and supporting sessions for multiple simultaneous users?
No, the backend SDKs always bypass security rules. Only the web and mobile SDKs that you use inside the client app make use of authentication tokens available from the user's prior sign-in.
You could consider using the REST API instead since it allows you to pass through a client auth token. It will be up to you to manage the transfer of that token manually.

Secure app using firebase auth to stop malicious use of the key which is on the client

I was wondering how to to secure firebase auth. I plan on using firebase JUST for user authentication (not using firestore or realtime db). Since the API key is exposed on the client, my fear is that a malicious user can find the key and start using it inappropriately. So far I've done the following to try to improve security:
Limit key use to a specific domain
Restrict the key to only be able to use "Identity Toolkit API"
Is there anything else I should do here?
My application should be the only one able to use my credentials to access the Firebase API.
For any app where you access a cloud based API directly from within the client-side application code, that is going to be a myth. The closest you can get within Firebase these days is with App Check, but that isn't available for Authentication calls at the moment.
Part of the reason for this is that the authentication API is quite well protected on its own already, and most abuse will actually not affect you as a developer very much. E.g. (ignoring phone auth) there is no charge for account creation, sign in, and any other operations.
I highly recommend checking:
Is it safe to expose Firebase apiKey to the public?
The documentation on API keys in Firebase.
The documentation on Firebase's security rules, which is how you can protect the Firestore and Realtime databases, and files in Cloud Storage.
The documentation on Firebase App Check, which reduces abuse for Realtime Database, Cloud Storage, Cloud Functions, and Firestore at the moment.
More of these previous questions on allowing only you app to access Firebase

How can I authenticate browser GET requests for an Express web app running on Firebase Cloud Functions?

I'm working on a web app running on firebase services. I've created an express back-end running on Firebase Cloud Functions and hosted on Firebase Hosting. I am trying to add authentication so only users with permissions can access admin pages.
I tried implementing session cookies as described here. It was successful but unfortunately was vulnerable to CSRF attacks since Cloud Functions strips all cookies without the name __session from incoming requests so the proposed csrfToken cookie solution is impossible.
I then considered using Auth's persistence in the client's local storage and sending the token in the header of a GET request. Unfortunately, I have only found tutorials on how to do this for requests within scripts e.g. for APIs, not for GET requests directly from the browser to serve a page.
It seems that there should be a simple solution. Am I missing something? Is cloud functions not meant for serving web apps like this? Is there another way to protect against CSRF without cookies? If Cloud Functions still allows the __session cookie is it meant to be used for storing the user's Auth Token and if so does it protect against CSRF anyway?
Thanks
In the firebase Cloud Function you can implement your own Auth. However Firebase provided its own Authentication method. In the Cloud Function, it is simple use the ‘functions.auth.user().onCreate() ‘ method. You can refer to Extend Firebase Authentication with Cloud Functions documentation for samples.
As for your GET question, are you asking about how to programmatically extract the parameter from the URL? It'ss similar to this; you can pull the URL and substring the part that contain the token.

How to secure REST API endpoints served via GCP Cloud Run?

I have a simple web site hosted in Firebase and it is making AJAX calls to REST API endpoints in GCP Cloud Run.
I would like to limit these endpoints only to the calls coming from this site hosted in Firebase. Any call coming from any other origin should not be able to use the endpoints. What is the best way to do this?
When I was not using GCP Cloud Run, I was doing a host check on the API side to make sure that request is coming from my client but now with Cloud Run this is not possible. What else could be done?
Please note that the web-site hosted in Firebase is very simple and do not do any user authentication.
Challenge: Restrict access to a Cloud Run service to a single web application, without relying on:
Restricting access to the web application
Imposing authentication on users
This difficulty is not specific to Cloud Run. It's a general challenge for static sites backed by APIs, and a reason why many sites have authentication. As mentioned in the question comments, a server-side "host" check is not a meaningful security layer, as everything in the HTTP request can be faked. I strongly recommend you not worry about keeping your API private or add user authentication to keep the system simple and access accountable.
If that's not possible, you can still take the authentication approach by creating a single user, embedding the credentials in the site, and rotating them regularly (by redeploy to Firebase Hosting) to prevent credential theft from having indefinite access to your API. Having Firebase Auth in the middle is better than a simple API key because it prevents replay attacks from accessing your API.

Can Firebase be used without clients logging in?

I am working on a project that might use Firebase only for messaging. The goal is for the following to happen:
App registers with Firebase on startup
App sends Firebase token to our server
Our server sends Firebase messages to all clients via the token from step 2
Note there is no step where the user will log into anything or enter any credentials. I am a little confused if this is possible in a production app, as most Firebase documentation talks extensively about different ways to authenticate, either via username/password, OAuth, etc.
The server will be sending different messages to different clients, but that logic will be handled by the server and not by different types of registration to Firebase. I know Firebase supports groups, but to make a long story short it probably won't be leveraged.
Can all this be done on Firebase? Is GCM a better match for these requirements? I feel like we would be throwing away 95% of Firebase and just trying to force it to simplify the messaging part.
Firebase Authentication does not at all affect the way that Firebase Cloud Messaging works. FCM only cares about the token for the app on the device as a means to target the app for messages. It doesn't care at all if the end user is authenticated by any means. If you want to associate a token to a user somehow, using Firebase Authentication or some other system, that's up to you.
FCM is an evolution of GCM. They are powered by essentially the same components. Using GCM doesn't give you any additional constraints or flexibility than FCM, except for the path to integration in your app.

Resources