Per-User File Upload Quotas with Angular and Firebase Custom Auth Tokens

Daz
Photo by chuttersnap on Unsplash

Working serverless with Angular and Firebase is great, but sometimes there’s a requirement that seems hard to achieve. Firebase Storage allows you to set complex security rules to manage access per user, and you can restrict upload size on a per-file basis. But, what if you need to restrict user uploads based on a per-user quota? This can be achieved by using Firebase Cloud Functions and Custom Auth Tokens.

First we define Firebase Storage security rules that allow users to upload to their own private area within the storage. Users can only read files that are prefixed by their user ID. They can only write to paths where their user ID matches AND the file path (resource.name) matches the path in the token AND the file size (resource.size) is smaller than the remaining quota specified in the auth token.

Firebase Storage Security Rules

The upload process is then achieved in 3 steps:

  1. Call a Firebase Cloud Function to generate a new auth token that includes the user’s remaining quota allowance.
  2. Re-authenticate with Firebase using the custom token.
  3. Upload the file to Firebase Storage.

First, on the Angular side, we wrap the storage upload observable to make it easier to compose. Notice that the upload path is created by combining the user ID and a file ID (generated elsewhere). This path is also generated as part of the token and part of the security rules check that these match.

Wrap angularfire2 storage upload observable for easier composition

The three steps to upload can then be composed using RxJS Observables. Notice that the same ID used for the file path is also passed as an argument to the getQuotaToken callable.

Three steps composed from separate Observables

For the Cloud Function, we first create a utility function that will take a user ID as parameter, list all the files for this user, and calculate the total sum of the file sizes. This function getUsage will be used by our Cloud Function:

Calculate the storage space used by a specific user

We can now define a Cloud Function that will generate and return the Custom Authentication Token. The Angular front-end code calls this Cloud Function and passes the generated token to Firebase. This token is then used by the Firebase Storage security rules when the file upload is attempted.

Cloud Function to generate Custom Auth Token

We have provided for a default quota, and allow a quota to be specified for each user. The constant DEFAULT_QUOTA should be set to a value in bytes. For example 5MB would be (5 * 1024 * 1024). You could allow users to purchase more storage space, in which case you would set the user’s quota value after a successful payment (using setCustomUserClaims). The example above is using a quota that has been set on the user with the DEFAULT_QUOTA value as a fallback.

Daz

Written by

Daz

Geocities Developer Expert. Keywords: Angular, TypeScript, JavaScript, Cyril Live Coding, Functional Programming

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade