firestore.get function not working in Cloud Storage security rules - google-cloud-firestore

I want to investigate that the user is admin or not but this is not working.
I get an error:
You don't have a permission to acces the object
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /articles/{allPaths=**} {
allow read;
allow create: if firestore.get(/databases/{database}/documents/users/$(request.auth.uid)).data.isAdmin == true;
allow update;
}
}
}
I try to rewrite the code, but this is not working too:
allow create: if firestore.get(/databases/{database}/documents/users/$(request.auth.uid)).isAdmin == true;

According to this Firebase blog Security Rules in Cloud Storage for Firebase now supports cross-service Rules with two brand new functions firestore.get() and firestore.exists(). Your rule should be
allow create: if firestore.get(/databases/(default)/documents/users/$(request.auth.uid)).data.isAdmin == true;
instead of
allow create: if firestore.get(/databases/{database}/documents/users/$(request.auth.uid)).data.isAdmin == true;
This feature allows you to read only the Firestore data belonging to the same Firebase project as your Cloud Storage; you will not be able to query Firestore data from a different project.
Firebase currently supports only 1 database instance per project so the name must be (default) in path. A similar answer explains this.
I have also recreated the issue at my end and it turns out this feature is only available to (default) databases.

Related

User can't write to Firestore database even though he is authorized

I created a rule in Cloud Firestore to read/write based on wether the user is signed in through Firebase Auth or not.
From my understanding based on what I read in the official documentation, the following code should allow the signed in user the correspodent permissions to the userID document inside the data collection.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/document {
match/data/{userId}{
allow read, write: if isSignedIn();
}
}
function isSignedIn(){
return request.auth != null;
}
}
Database image:
The idea is that after the user logs in, the code I wrote should verify if there is a document called ReservedID in data/userID/ReservedID, and if there isn't, create one for him, however, this collection is never created.
It does work if I remove the security rules.
Image of the error that shows in Android Studio:
However, after signing in using mAuth.signInWithEmailAndPassword, the user still can't write or read from the database. The Android Studio Logcat provides this message:
PERMISSION_DENIED: Missing or insufficient permissions.
Did I misunderstood how to properly set these rules in my database? Or could it have something to do with the code itself?
It looks like there are some issues with the code.
The match statement should specify the path to the collection and whole documents, rather than just one document. i.e you are using the path for single document match /databases/{database}/document instead of below path:
match /databases/{database}/documents {
match/data/{userId}{
}
With the above changes, the code will look like this:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match/data/{userId}{
allow read, write: if isSignedIn();
}
}
function isSignedIn() {
return request.auth != null;
}
}
You can verify this on playground

unable to download images form firebase storage [duplicate]

I have a function that successfully uploads an image to my cloud storage bucket.
With another function I want to get the URL of the image to show it on my page (With <img.../>)
getImageUrl(id: string) {
return this.storageRef.child('X/' + id ).getDownloadURL();
But when I do this.. I get an 'invalid' URL and when I copy the URL and go to it, I get the following message:
{
"error": {
"code": 403,
"message": "Permission denied. Could not perform this operation"
}
}
I read somewhere that this might be because there is no token attached in the URL, but how can I enable this?
The last couple of days I have been trying to understand Firebase Storage rules and I don't know why but when I separate rules for writing and for reading like this for example:
allow write: if request.auth != null && request.resource.size < 3 * 1024 * 1024;
allow read: if true;
the code works great and I can write and read using getDownloadURL(), but when I use them together like this:
allow read, write: if request.auth != null && request.resource.size < 3 * 1024 * 1024;
I got the same error as you:
{
"error": {
"code": 403,
"message": "Permission denied. Could not perform this operation"
}
}
I can write when using them together, but when I try to read the file using getDownloadURL(), the issue appears. Maybe you could try separating the rules as I mention and see if it works. I hope it solves your problem. Also, don't forget that the rules are live after 5 minutes from the moment you set them. Good luck.
You have to set Storage Security Rules, read more about this here
Just faced similar issue with my project, if anyone is still struggling with it, you have to provide proper rules for your Cloud Storage from the Firebase console.
Checkout this link to get full detail of the rools.
If you are uploading any object on your storage, you will require to add write rule under Firebase console > Storage > Rules.
I've faced the same issues with access to my storage files in my iOS project. I don't have any custom security rules. Just what's default in configuration. Breaking rules to new lines helped!
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow write: if request.auth != null;
allow read;
}
}
}
I don't know if this is some firebase bug but it helped:)
just use this rule for image
service firebase.storage {
match /b/{bucket}/o {
match /images/{imageId} {
// Only allow uploads of any image file that's less than 5MB
allow write: if request.resource.size < 5 * 1024 * 1024
&& request.resource.contentType.matches('image/.*');
}
}
}
Separating read and write in different lines makes the issue go away, plus in your url you can just append ?alt=media to render it on screen.
allow write: if true; //your conditino
allow read: if true;
You need to use the getDownloadURL method. This will allow you to obtain the URL needed to download the image or for reference in your own html.
See the reference documentation below:
https://firebase.google.com/docs/storage/web/download-files#download_data_via_url
For my case, I accidentally delete the files before so it needs to show the File not found message but don't know why it was showing the Permission denied message.
Edit:
Although this was a temporary fix but it comes with security vulnerability (refer to #Joao Gavazzi's comment).
I was able to solve this by changing the FirebaseStorage security rules from default to:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if true;
}
}
}

Insecure rules in firebase

I understand it's not good to set your read and writes to all users on Firebase;
But what if you leave your reads to all and your writes to only authenticated users?
What is the worst thing that could happen?
Is it easy for someone to gain access to the firebase project?
I'm currently using cloud firestore.
Sorry if this seems a little dumb, I'm new to this:
Thanks,
Jacob
EDIT: Current Rules:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: if true;
allow write: if request.auth != null;
}
}
}
I've worked with Firebase for a long time and I've come to realize that the rules are a very good way to prevent unauthorized access to your data, by any third party - especially when used in tandem with rules set within your Application (be it Web, iOS or Android).
Personally, I usually set my rules to the following:
service cloud.firestore {
match /databases/{database}/documents { match /{document=**} {
allow read, write: if request.auth != null;
}
This means that only logged in users are allowed to access the data and write data as well.
If, instead, you want users to access the data without being logged in but only write data if they're logged in, then I would suggest these rules:
service cloud.firestore {
match /databases/{database}/documents { match /{document=**} {
allow read;
allow write: if request.auth != null;
}
In terms of how easy it is to access a Firestore Database when not authorized to:
Google has done a good job at keeping things secure.
Setting up these rules and some other checks within your Application is enough to keep things secure.

Basic Cloud Firestore security rules setup

I am currently using this default code to secure my Cloud Firestore database:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth.uid != null;
}
}
}
This code works fine and the simulation is fine.
I tried to update the code and use the new default code I find in every guide:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid != null;
}
}
}
But this code fails every time, the access is not granted.
In the simulation, I just try to read a document in a Collection named "parameters".
Am I missing something here? My plan is to harden the security access afterwards.
Ok my bad, I actually realised that the database access rules and the storage access rules have their own and separate security panels.
I was trying to update the storage rules with the default database rules...

Reading and writing in firestore only through cloud functions

I want to set my Cloud Firestore database permissions so that no one will be able to read and write from it except through Cloud Functions.
How can I do this?
My guess (according with Firestore docs) is that I have to set the right condition for what I want, but what condition would it be? I don't know how to "communicate" the cloud function call with the rules.
service cloud.firestore {
match /databases/{database}/documents {
match /<some_path>/ {
allow read, write: if <some_condition>;
}
}
}
Simply eliminate all the rules and replace them with a rule that rejects everything:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
With nothing explicitly allowing mobile and web client access, none will be allowed. The server SDKs always bypass security rules, so as long as the service account that you use to initialize the SDK has write access, it will work. The default service account used in Cloud Functions should be fine.