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;
}
}
}
Related
I've been trying to get the Firestore rules to play nice for a while now and every time I think I get them right, another portion stops working for some reason.
I'm trying to have some simple rules, if you made the document that document and any child documents or collections, you can create, edit and delete them. I thought this was pretty simple but alas I keep getting permission denied errors.
Rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, update, delete: if request.auth != null && request.auth.uid == userId;
allow create: if request.auth != null;
}
match /users/{userId}/{document=**} {
allow read, update, delete: if request.auth != null && request.auth.uid == userId;
allow create: if request.auth != null;
}
}
}
When doing just the match /users/{userId} I was able at one time able to create user documents but I couldn't create child documents or colletions.
When doing just the match /users/{userId}/{document=**} I could no longer create users but any existing users I could add child documents and collections and do everything expected.
This combination of both rules doesn't seem to work either.
I keep getting [cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation. when I try to create a user with this statement:
await FirebaseFirestore.instance.collection('users').doc(googleUser.uid).set(
{
'created': now,
'lastLogin': now,
'name': name,
'email': email,
},
);
Now nothing works. I deleted all my authentication accounts and my Firestore data and wanted to start over but it simply will not create the data in Firestore.
Any suggestions would be greatly appreciated as I'm going in circles and nothing is working anymore which is extremely frustrating as it did at one point but no longer does.
edit All of my testing is being done on a real Android phone.
After walking away from my computer and thinking more, I figured out what it was. My App Check debug token changed somehow.
Once I added the new value from the debug console everything started working again.
I'll leave this answer here in case this saves anyone else some headaches in the future!
Edit: Additionally, ones App Check debug token will change anytime you clear storage on your app on the device. Which is why mine was changing.
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
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...
I need some help making my security rules for firestore work.
These are my firestore rules:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
function isAdmin(uid) {
return (uid in get(/admin/administrators).data.uid)
}
allow read;
allow write: if request.auth.uid != null && isAdmin(request.auth.uid);
}
}
}
In document /admin/administrators there is a field named uid containing an array of UIDs of administrators which are allowed to write in the database.
After I logged in as one such administrator and tried to add a document to another collection. (Specifically, the call in my Angular application using Angularfire 2 is this.afStore.collection(collection).add({});) I received the error Error: Missing or insufficient permissions.
Any help appreciated (including "there's obviously a better way to do this")
You should enter the absolute path of the collection you're trying to reference. Change the (uid in get(/admin/administrators).data.uid) to get(/databases/$(database)/documents/admin/$(request.auth.uid)).data.uid
I've seen several questions about placing specific security rules in Firebase. I've figured out how to do this in those cases. Now I'm saving information by authData.uid and getting this info....
[Firebase] Using an unspecified index. Consider adding ".indexOn": "4eb8920a-e407-4488-bce4-c6f64f7b0891" at /UserVideo to your security rules for better performance
How can I add such security rules for unique keys and how?? Here is my query...
let videoRef = self.ref.childByAppendingPath("UserVideo")
videoRef.queryOrderedByChild("\(currentUser)").queryLimitedToFirst(1)
.observeEventType(.ChildAdded, withBlock: { snapshot in
if snapshot != nil
Any insight is welcome!!
* UPDATE *
Yeah. I forgot to add that currentUser is...
let currentUser = ref.authData.uid
And the query actually gives back relevant information. It just also includes the specified warning. Will try the second answer a few times and update this post if it works. If anyone else has any ideas please post.
See this: Security & Rules Quickstart
Security and Firebase Rules are used to determine who has read and write access to your database as well to ensure the structure of that data. They are found in the Security tab of your App Dashboard. They come in three flavors: .write, .read, and .validate.
IN answer to your question, add security rules for unique keys by using the validate and write together.
An example would be:
{
"rules": {
"foo": {
// /foo is readable by the world
".read": true,
// /foo is writable by the world
".write": true,
// data written to /foo must be a string less than 100 characters
".validate": "newData.isString() && newData.val().length < 100"
}
}
}
Does this help?