When using Firebase Storage with the Javascript SDK is there a way to only let users who pass the read permissions view an image. The issue I'm running into is once I get a storage reference the only way to view the image in a browser is via the download url, which has no permissions attached to it. What I am wanting is a URL only accessible by users who pass the read permissions. Is there a way to do this currently?
Edit 1:
Currently, I am getting the url like this:
const firebaseUrl = 'gs://bucket/object';
const storageRef = firebase.storage().ref();
storageRef.child(firebaseUrl).getDownloadURL()
.then(url => console.log(url))
.catch(err => console.log(err));
And am putting the download url in the img src.
<img src="url generated from above code" />
How can I have the image display only if an authenticated firebase user with permissions is viewing it? If the url is viewed in an incognito window it will return a 403 or something.
No, download URLs are always universally accessible until its token is revoked. This behavior can't be changed. If you need to apply security rules to a file, you have to use the SDK to download the content, since the SDK is aware of the user signed in through Firebase Authentication.
Related
How can I protect my uploaded document in Firebase?
For Example, this is my uploaded document URL:- https://firebasestorage.googleapis.com/v0/b/sapient-logic-368311.appspot.com/o/coder.JPEG?alt=media&token=55d1a727-956f-434b-bdad-a08b8ef133d0
Anyone can able to access and see my uploaded document by using this document URL.
How can I protect the uploaded document, then only authorized persons can access the uploaded document.
I want If anyone get document URL although Can't be access or see document
I want like this If anyone try to access my document using document URL:-
Or Can I make private bucket in Firebase ?
Anyone can able to access and see my uploaded document by using this document URL.
That's correct. And this is happening because you have shared the entire URL along with the token, which is not correct since the token should act as a security measure to restrict access only to those who possess the token.
So the best option that you have, would be to store such a URL in a database like Firestore or the Realtime Database and only allow access for reading the URL using security rules.
Remember, that token is created automatically whenever a file is uploaded to Cloud Storage for Firebase. So don't share that token with anyone.
You can write rules in it which help you who can read or write the data.
If a specific file is thought to be private, then no client normally should have access to the URL token.
If the case is the file URL was public and you want to make it private, you can modify the access token without being obligated to re-upload the file or changing its path.
I don't know what platform you are working on, but from the Python SDK, it can be done this way:
from firebase_admin import storage
from uuid import uuid4
bucket = storage.bucket()
blob = bucket.blob(path_to_file)
token = str(uuid4()) # Random ID
blob.metadata = {
"firebaseStorageDownloadTokens": token
}
blob.patch() # Updates changes
After this, the previous URL will be unusable and firestore will respond with the error you mention:
{
"error": {
"code": 403,
"message": "Permission denied."
}
}
Note that this solution applies for full-stack applications, where backend is what uploads the file to the Firebase Storage. If your project consists of the client connecting directly to the Firebase Storage, then you should take a read about the security rules and use them as a pseudo-backend.
I am using firebase, react and react-native to develop an MVP app where users can upload image files and other users can retrieve them for viewing, and I am using firebase storage and the getDownloadURL() function.
I know that there are other ways of retrieving firebase storage files, but I want to use the downloadURL so that unauthenticated users may also view the images.
I know that downloadURL is public and access to files cannot be restricted even by firebase security rules.
Nonetheless, there is the revoke function where I can supposedly revoke the access token, i.e. the downloadURL. At the firebase console, I tried it out. It turns out that every time I revoke it, firebase generates a new one as replacement. More problematic is that I can still use the old (revoked) URL to access the image files. I checked out at the browser developer tool. The URL used by the browser was indeed the revoked URL. I used a new browser to ensure that the problem is not related to the cache. Even if I use a react-ative app, the same problem appears.
The image cannot be accessed only if I completely delete it from the firebase storage.
What is the problem here? Have I missed something?
I have looked up the firebase documentation and searched for similar issues on stackoverflow but cannot get an answer. Other people don't seem to have this problem.
The reason why you can still access the revoked urls is because in your firebase storage rules you have accepted reads for all users, whether authenticated or unauthenticated.
To prevent access to revoked urls, use the following in your firebase storage rules.
NB// This will require all users to be authenticated inorder to get the download url
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
I've read the documentation and I just don't get the fundamental concept about how to access files.
I want to use Firebase Storage in a web app. I have pre-uploaded images that should be accessible to the public. I see that when you upload from the Firebase Console, you get a link to that asset. I see that the token is in the URL and that you can revoke this token, (See screenshot)
So... is that url with the token supposed to be secret? It would be bad to use that link in public html, right?
If so, how can I generate a public link that I could use in an <img src="link-here.com" /> ?
is that url with the token supposed to be secret?
It's a secret that gets shared with everyone who should be able to access the object.
It would be bad to use that link in public html, right?
Only if that would expose access to those who should not be able to download the object.
how can I generate a public link that I could use in an ?
Follow the instructions in the documentation for downloading data via URL. You will use getDownloadURL() to asynchronously get a URL that has the token embedded in it.
I have set rules for our Firebase Storage to only allow authenticated users to interact with it.
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /something/{allPaths=**} {
allow read, write: if request.auth.uid != null;
}
}
}
However, when I browse the details of the assets saved in the storage in the Firebase Console, I do find for each of these, a link to open these publicly (when I open the details of a file), for example:
https://firebasestorage.googleapis.com/v0/b/${my-project}.appspot.com/o/${my-file}?alt=media&token=49385ae5-4df6-44ef-a313-8d1f07b59111
My guess is that this link is the downloadURL and the public access is granted through the token.
Therefore I understand that the storage content is actually not fully private because even if I set strong rules and even if I personally and my apps don't generate download URL, Firebase still generate automatically such url for each file and therefore, even if token are hard to find, the content is in any case accessible online publicly.
Is my understanding correct?
Or the link I found in thee Firebase console isn't the download url but a temporary link respectively the token provided by the console as an expiration life?
Or is it possible to set the Firebase Storage Bucket to not generate any download links ever?
Anyone who has a downlaod URL with a valid token can access the content from anywhere. However, if you never expose that URL to anyone, it's essentially impossible for anyone to guess that URL, even if they know the path. The token is random and contains a tremendous amount of entropy.
If you're concerned about anyone guessing this URL with the correct token, you should also be concerned about two random atoms in the universe colliding with each other. (That's a slight exaggeration, but you can do the math if you assume that each character of a token is a valid hex digit.)
If you're still paranoid, and you don't want to generate any download URL at all, you will have to manually revoke the download URL tokens, and use an upload technique that doesn't also create a download URL, and never call getDownloadUrl on any file from a client app.
I am building a small web app using Firebase.
There is the steps :
The User connect (Firebase authentication)
The user upload an image (Firebase storage)
The user can download or see his images
<img [src]="imageFromFirebase">
The url given by firebase looks like :
https://firebasestorage.googleapis.com/v0/b/<Your API>/o/userData_YOQioOsgzUP0B0fTAa6BVK5KOxo2%2Fimages%2F-L-w7THGfT6qmX9UhLsK3.png?alt=media&token=61f6edf9-188e-4177-9ee2-34635ebc5a4a
With this URL, I can display the image on the browser only if the user is conneted.
The real problem is that I copied this URL and past it in another web browser (without being authenticated)
And SURPRISE !! this image is displayed !
I don't understand why the image is displayed ?
It is normal ?
Thank you !
When you generate a download URL for a file in Cloud Storage for Firebase, anyone who has the URL will be able to download its contents. This is by design. The URL is "unguessable", so only people who actually have the URL will be able to see the content.
If you don't want people to see that file, then don't share the URL. If the URL is accidentally shared to others who shouldn't have access, you can revoke the token that allows everyone to see the content.
As I know, the right way for storing then retrieving file is that you upload file to a path (folder/filename), store that path (a field in post for example) then when you want to show it, pass the stored path to the getDownloadURL function, it will return a full url that can be use as src attribute for img tag