-
Notifications
You must be signed in to change notification settings - Fork 927
Firebase Storage READ security rules: almost pointless, as currently implemented. #5342
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@LeadDreamer You state you’ve started a wrapper project. Did you consider just making a patch that gets automatically installed at I’ve resorted to this approach once with Firebase clients, and now considering it with Raygun client. If npm dependencies are almost there - ”needed code already exists” - I find this a reasonable way to not be kept back by the often sluggish development of libraries that I cannot directly influence. |
It is a long standing feature request and we are experimenting with it recently in #4973. |
Beyond the For example:
...can be accessed by me because I have Access to my google account, but cannot be accessed by others. Note this access is INDEPENDENT of security rules. Note it actually gets a 307 status and redirected to:
On the other hand:
has access by ANYBODY (status 200) whether authenticated or not, while
cannot be accessed (403 error) by anybody, authenticated or not. So there is currently literally only the two scenarios:
I intended on hacking some code to axios or fetch a file from storage into my browser javascript, just to see if it can be done (I doubt it) |
With much experimentation, here is what I've learned so far for images stored in Firebase Storage (private information obscured): => With a token on the URL, security is bypassed altogether. => WITHOUT a token, it is possible to set rules to allow access at various levels of a hierarchy - but ONLY simple on/off, not conditional on WORKS
fetched from URL
the above ALLOWS for images to be fetched IF they are stored under Also, rules can be written to ONLY permit access to LOWER levels in the hierarchy, for example:
fetched from URL
will succeed, but
will properly fail Note that these work regardless of whether accessed in an authenticated page or not. WHAT DOES NOT WORK
fetched from URL
WILL NOT SUCCEED, whether fetched in an authenticated session (using Auth, Firestore and Cloud Functions) or not. REFERENCE RESULTS:
fetched from URL
HEADERS:
FAILING EXAMPLE
fetched from URL
HEADERS
FURTHER REFERENCE, SUCCESSFUL FIRESTORE CALL: HEADERS
|
More interesting data points:
...which calls
which sends TWO requests to the backend.
which returns
OBVIOUSLY, WHY IS THIS INTERESTING? BECAUSE the above call FOLLOWS THE SECURITY RULES.
a fetch OUTSIDE OF AUTHENTICATED CONTEXT of:
returns THE METADATA
a fetch OUTSIDE OF AUTHENTICATED CONTEXT of:
FAILS WITH 403 status - AS IT SHOULD The INTERESTING part is that WITHIN the authenticated context, the above DOES return the metadata (200 status) - as it should!!! BUT BUT BUT, we then see
FAILS with a 403 status - THAT fetch requires a token. Security rules SHOULD HAVE ALLOWED THAT FETCH, The only difference is the parameter |
So continuing successful vs unsuccessful fetches, both in authentication context: SUCCESSFUL (SDK call FirebaseStorage.ref("/defaultImages").child(filename).getDownloadURL() )
UNSUCCESSFUL (HTML embedded image)
with headers:
|
Researching a canvas approach that might help, based on: |
Using
|
Using
|
What Should Work But Doesn'tAdding
The reason given isn't really correct, though... WHY?Look at these response headers:
What's missing?access-control-allow-credentials is NOT returned by Google's servers. Why isn't it returned by Google's Servers? I don't know. |
Hacky Code that fetched Image within Security Rules
...using JSX...
|
Probably related to this:Google Cloud Storage |
Security rules are primarily aimed at use with SDK calls (as you noted, You can of course drop down to the Google Cloud Storage REST API and use that with There's certainly more that we can do here in the future to fill out the security rules story (such as some day allowing you to do get() requests against your Firestore data to help with roles and groups), but functionality is limited in scope for now as described here. |
Yes, that is the reason I want to have the Rules apply - but FIRST the rules have to be enforced at all. I have gone into the code to see exactly how your code creates the headers, and it now seems apparent that you are using the The Google Cloud Storage REST API doesn't seem to have the same hierarchical Rules structure that Firebase Storage does - but since your code can follow the rules, mine can as well. |
A proposed Browser/Node-side solutionNot the most straight forward, due to browser limitations. It is NOT possible to add custom headers directly to JSX
where: Javascript
Explanationwhen the
ResultA file (in this case, an image) is fetched from Firebase Storage, following all of the Security Rules set therein. No permanent token needed. Only authenticated users have access. Going ForwardI am likely to added a class to |
What Would be Better!!GOOGLE should set Firebase Storage to allow the use of Credentials, which CAN be added to both |
What Might Be Acceptablean extremely simple Although I suppose I could just strip the silly token. The problem is that would be on the client side - I would rather the token never be on the client side. Same issue for using Still comes down to...MUCH MUCH MUCH BETTER to allow the use of the credentials, verified on the SERVER side. |
I'm facing the same issue, I want urls to my files saved in firestore for quick access but I also want them to respect the rules I wrote for the files, right now if I generate a download URL it bypasses the rules, this means that the entire system is useless, might as well remove rules. |
Environment
The problem
So, Google Folk:
Would someone please tell me under what conditions would any authenticated rule ever be passed for reads in the Firebase client SDKs?
For Example:
It seems obvious enough - until you finally realize that the client SDK's failed to implement the (extremely obvious) .get() method on a storage reference.
.getDownloadURL()
creates a TOKENIZED URL, which BYPASSES the above security rules.Use of an UNtokenized URL in a browser context (such as an image URL) DOES NOT INCLUDE authentication headers, so the above rule will ALWAYS fail.
IF there is no
.get()
method, and...IF
getDownloadURL()
always generates a URL that bypasses the rule...What the ever-loving-heck is the POINT of such a rule?
And PLEASE don't repeat the usual pushback of "once a URL is in the world what's the point of security" - I have very good reasons (which I can explain in confidence, out-of-band) why I want this level of control.
It's ALSO clear someone INTENDED there to be this level of control.
I can, of course, write a wrapper that some-way-or-another gets the authentication headers and add them to an HTTPS request (SPECIFICALLY WHAT YOUR CODE IS DOING ALREADY) to download an item (whether image or not) to the client JS...
But WHY would I do that when I can see that virtually ALL of the needed code ALREADY EXISTS in the SDK, you just didn't expose a
.get()
method...so:
either some way to cause browser image fetches to include/use the cookie for authentication (is it a CORS policy?)
OR
just simply add the
.get()
method to StorageReference in the client SDK(hey, put me on contract, I can probably get it done - I've already started poking in the repository, which is why I know most of the code structure is there)
Steps to reproduce:
(FYI, I am creating a @leaddreamer/firebase-wrapper library for my own use, which INCLUDES wrapper to make the client API almost identical between client and Admin SDK. Obviously the
.get()
is trivial in Cloud Storage. It doesn't help the browser, though)The text was updated successfully, but these errors were encountered: