Reputation: 115
On my Firebase app, I'd like to know the recommended way to make a server-side request to Cloud Storage for Firebase on behalf of a signed-in user (authenticated via ID token), with security rules applied to the request (i.e. not with the Admin SDK).
The overall app flow currently looks like this:
x-forwarded-authorization
request header (which contains the ID token originally provided by the client) forwarded by API gateway to then make a request to Firestore's REST API, so that the request can be evaluated by security rules.For Cloud Storage, I'd like to do something similar to the Firestore case above, but there isn't a Firebase-specific REST API available in the docs. It's possible to just let the client make requests directly to Firebase (as suggested in this answer), but would prefer to keep the logic in the backend.
Are there alternatives to doing this for Storage? Please feel free to also point out if there are better ways of handling the Firebase Auth and Firestore cases mentioned above. Thanks!
EDIT: Adding more possible solutions as I find them
auth=IDTOKEN
query parameter to the Firebase REST API:Once you have an ID token, you can pass that to the REST API via the auth query parameter to authenticate a request. The request respects Firebase Security Rules as if the end user logged into the client was making the request.
Upvotes: 3
Views: 574
Reputation: 115
After considering the various options above (thanks Frank and som!), the best choice in my situation was to change things up and make Storage requests directly from the client. The 2 main reasons were:
When making the request from the client, som's answer above and this answer may come in useful if there's a XMLHttpRequest is not defined
error
Upvotes: 0
Reputation: 2477
Edit 6 Jan 2020: This method has had a couple of days testing under heavy-load. See bottom for some minor new requirements.
Original response: This isn't an answer, so much as an in-ecosystem workaround (that works for me!)
Basically, I have a similar-ish use-case with regards an offline-first/potentially insecure iot device that needs auth based storage access with security rules. This morning I took a peek at the Firebase js sdk repo and noted that a native XHR API is the main piece missing from a working node implementation.
I detailed my workaround on this github issue ... included here for convenience:
.. patching the storage library with an XHR polyfill actually appears to work (Node 15 / minimal testing so far). Specifically I've installed xmlhttprequest-ssl and imported it at the top of the storage module (in my case line 5 in
@firebase/storage/dist/index.cjs.js
):
var XMLHttpRequest = require("xmlhttprequest-ssl").XMLHttpRequest;
Back in the app I import
firebase/storage
as normal, then just load files from the local file system and upload as per the standard Firebase API:
import { firebase } from "@firebase/app";
import "@firebase/storage";
/* include Firebase setup, etc. */
const filename = 'offline-user-generated-image.jpg';
const file = fs.readFileSync(filename); // for brevity only
const ref = firebase.storage().ref().child(`test/${filename}`);
// use the buffer's underlying arraybuffer
ref.put(file.buffer, {
contentType: 'image/jpg', // defaults to 'application/octet-stream'
customMetadata: {
uid: 'abc123', // for enhanced security rules
},
})
.then(() => console.log('done'))
.catch(e => console.log(e));
Storage rules apply to uploads (woop!) and security tokens and custom metadata are applied as expected. Also tested with `putString'. This solves some fairly drastic workarounds for my use case, as it means I can keep my logic/auth/etc. entirely within the Firebase ecosystem. Keen to hear others thoughts.
Note: I'm using patch-package to ensure the patch stays intact across installs / upgrades.
Update 6 Jan 2020: Some extra bits and pieces
It turns out that there is an uncleared timeout in the storage package that causes hell with node processes (and is likely a resource hog in all environments) .. I've submitted a PR (pretty much a clearTimeout
) that resolves the issue, but in the meantime this will also need to be manually patched unless you can safely process.exit(0)
in your code.
Upvotes: 1
Reputation: 599706
There is no way to enforce Firebase's security rules for Cloud Storage when using the Admin SDK. Firebase doesn't provide a documented REST API for Cloud Storage, and I doubt the Google Cloud REST API for Storage accepts Firebase ID tokens.
So I don't really think you have good options to do this from the server on behalf of your users. The two options I can think of:
Upvotes: 1