As written in Firestore documentation here I have a security rule like this:
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, update, delete: if request.auth.uid == userId;
allow create: if request.auth.uid != null;
}
}
}
this rule works when I get authenticated with client library but not when I use server library as written in firebase documentation
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 Cloud Identity and Access Management for Cloud Firestore.
How to replicate this security rule to service accounts roles?
Code that uses the Firebase Admin SDK with a service account to access Firestore currently can not be scoped to a particular user ID for the purpose of enforcing security rules. All access with the Admin SDK will bypass security rules and have full control of the database.
Note that this is different than Realtime Database, which does have such a feature.
Related
At this moment we have 1 Firebase Function running that connects to a Firestore database instance. It correctly connects to the Firestore database using the rules below, however this is insecure.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
It is however unknown to me how we should secure this if we don't have Users in our application. It is not multitenant. We just do HTTP calls to the function and it saves something in the database.
To build user-based and role-based access systems that keep your users' data safe, use Firebase Authentication with Firebase Security Rules.
We do not have user data.
Note: The server client libraries bypass all Cloud Firestore Security Rules and instead authenticate through Google Application Default Credentials.
If we change our write rule to write: if request.auth() != null our application fails to save.
However, we can call getAuth() and then signInAnonymously(). But how does that make it more secure? And how long will the function remain authenticated?
We have read the documentation at https://firebase.google.com/docs/rules/rules-and-auth and https://firebase.google.com/docs/firestore/security/get-started. But as we don't have users in our application, it seems unclear to us how to secure Firestore using firestore.rules.
Concrete: How do we secure a Firebase Firestore without using Firestore Authentication? Or is it a must?
When not using Firebase Authentication, you cannot get details of user who is making the request. request.auth will be null in this case and hence request.auth() != null fails.
When you use signInAnonymously() the user is signed in with Firebase Auth and request.auth contains details of that user. However, once the user logs out of an anonymous account by any mean, there is no way to log back in with that account and user won't be able to access their data again.
If you use your own authentication method, using Cloud functions to retrieve data would be best so you can authenticate user using your auth system and then serve data if authorized.
I currently have a GCP/Firestore Cloud Function writing to Firestore. And a NuxtJS client reading from said Firestore DB.
My NuxtJS client does not use user-based authentication. It is a news site that shows publicly available information.
I'm trying to configure the Firestore security rules to only allow reading/writing/updating from applications with an active service account for this Firebase project.
Currently, I'm getting an error on my client that says FirebaseError: Missing or insufficient permissions.
I have verified that the service accounts in question are still active and have the appropriate permissions.
I'm guessing that I'm missing something in my security rules.
My current security rules are as follows:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null; }
}
}
Any direction is greatly appreciated.
I'm trying to configure the Firestore security rules to only allow reading/writing/updating from applications with an active service account for this Firebase project.
The security rules are effective on requests made using the Firebase Client SDKs only. The Admin SDK which uses a service account bypasses all security rules and has complete access to your Firebase project. Since the users don't have to login in your application, you can set all the permissions to false:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
With these rules, only the Admin SDK can make requests to Firestore. If you are using runtime config to store your credentials, make sure the service account is in private so it can be access on server side only.
I have a Flutter app that uses an API to pull data. My API key is the only thing stored in my entire Firestore database. My Flutter app retrieves the API key from Firestore and then uses it to fetch data.
My app also has anonymous authentication enabled. My app creates an anonymous user when the app is launched. My app does not allow users to create an account or sign up.
Below are the Firestore security rules that I currently have and I'm unsure if they can be improved to make them more secure from malicious attacks. My rules point to a very specific document myAPIKeyDocument, allows get only for authorized users, and does not allow write.
Are these rules safe as is or can they be improved if the only permission I want my app to grant is read access of my API key for anonymously authenticated users? And also, does if request.auth.uid != null; really make a difference at all since all users of my app will be automatically anonymously authenticated?
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /myDataCollection/myAPIKeyDocument {
allow get: if request.auth.uid != null;
allow write: if false;
}
}
}
If any user in your app having access to your API key is secure enough, then yes you are fine. Personally I would migrate any logic that requires an API key out of the client app and into Firebase Functions. That way you can more tightly control security to allow only requests from your app.
With anonymous authentication your current rules are about as good as it gets with the current structure of your project.
I'm dealing with an Angular app that authenticates users through a third party system.
I'm trying to figure out how to best secure the Firebase instance, which leverages Firestore and storage buckets.
I'm new to Firebase and when I look at the documentation I see security rules that look like this.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
I can add authentication, is that's the best path forward. It seems redundant since they've already been authenticated by the other system.
On the other hand, the authentication provider is not currently supported as a Firebase authentication provider.
Is there a simpler way to limit access to Firestore and the storage buckets that doing Firebase Authentication?
The idiomatic approach is to implement a custom sign-in provider. That essentially puts your authentication data into the request.auth variable.
I use a service account to interact with my firestore database (native/realtime mode) from my backend application.
I'm trying to reduce the privileges of the service account. When I set permissions to:Firebase realtime database admin all my calls fail with permission denied.
When I set them to Firebase Admin (i.e. access to everything, also image storage, functions etc) the api calls work perfectly.
P.s. since it's a service account it doesn't need security rules, so they are set as:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
How can I set permissions only to the database?
For who has the same problem, I figured out the correct permission: Cloud Datastore User
This works even if you are using a firebase/native mode database not in Datastore mode.