This past week I’ve been attempting to add support for uploading to Backblaze B2 (https://github.com/Klowner/uppy/tree/backblaze-b2), but due to the way their API works in combination with my relative inexperience with Uppy, I’ve arrived at the point where I feel like I should reach out for community input (assuming this is even a desirable addition to Uppy).
I’ve successfully managed to upload a multipart file directly from the browser to B2 via Uppy, but due to the way Backblaze’s API works, there appears to be no way for for an authoritative server (such as Companion) to granularly authorize uploads to a particular file path within a bucket.
B2 enforces access restrictions at the application key level, as well as CORS rules on buckets. To upload a file, an API call to B2 with the application key is performed (
b2_authorize_account), which returns an authorization token. The authorization token can then be handed off to the client where they can initiate uploads. All of this seems fine, except from what I can tell, there’s no way to restrict that authorization token from being used repeatedly, so a malicious user could just upload a ton of random junk to your bucket.
So, I’ve arrived at a few options:
A) Companion creates an application key for each user session (B2 has a total limit of 100 billion app key creations per account) with file prefix restrictions so uploads can only go to a certain directory within a bucket.
B) Create a write-only application key which Companion passes to B2 for authorization, and then pass that authorization token to the Uppy client for uploading. Each B2 file upload creates a unique file identifier, so the client could then tell “I just uploaded fileId” to Companion, then Companion could use a less restrictive application key to copy the file to a proper location within the bucket.
C) Uppy sends all file data directly to Companion and then you never have to worry about sharing sensitive auth tokens, but I feel like this kinda defeats the entire purpose. (Unless this is exactly the purpose of what companion is for? The docs aren’t super clear regarding the routes that the data takes)
None of these seem perfect, but I’m leaning towards B.
Thanks for reading! Any input is greatly appreciated!