Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a public share-link for private resources in firebase database

I created a simple database in firebase which backs up data from an android application and has the following structure:

-item
  -owner_id
  -property1
  -property2
  ...
  -subitem
    -more properties

And tht's already it. But now I want to add the option to create a link like you can do it in google drive or dropbox, that allows everyone with the link to see the data. (With no login required).

So I thought, I'd create a password/key for every item, which would be included in the link and allows users to access the item, even when not signed in. But I struggle to find a solution that makes this possible with firebase's access rules, since I don't want to have every item publicly readable. Are there any options to do this without custom tokens created by a separate server?

like image 217
moritzbruder Avatar asked Oct 30 '22 01:10

moritzbruder


1 Answers

I can think of two fairly straightforward approaches here:

  1. Set up an endpoint that handles the requirement.
  2. Handle the requirement through the REST API of the Firebase Database.

Set up an endpoint that handles the requirement

The first approach requires that you set up a server or implement a Cloud Functions HTTPS endpoint that takes the user request, validates the password/key from the link and then look up and returns the data if all checks out.

This seems quite straightforward, but it does mean that you're adding server-side code, which I never like. That's why I always look for an approach that can stay within just the Firebase Database.

Handle the requirement through the REST API of the Firebase Database.

The Firebase Realtime Database has a REST API, where you can directly access the data at a specific point. E.g. https://yours.firebaseio.com/items/item1.json This REST API still follows the security rules that you have for your database, so you'll either need to authenticate the URL with an access token, or make it publicly accessible. Since generating tokens is rather involved, I'm going for the latter here.

The thing to realize is that we can't pass a email/password/token to the REST API in this case. But what we can instead do is putting the data at an unguessable path. So pretty much instead of https://yours.firebaseio.com/items/item1.json?token=verysecrettoken we'll use https://yours.firebaseio.com/public/verysecrettoken/item1.json. In the latter I've put the public data under a top-level public node, which makes it easier to secure. Just be sure to not make the entire /public node readable because then someone could https://yours.firebaseio.com/public.json to get it all. More likely you'll do something like:

{
  "rules": {
    "public": {
      "$secret": {
        ".read": true
      }
    }
  }
}

With this structure only somebody who knows a valid $secret value, can read the corresponding data.

like image 54
Frank van Puffelen Avatar answered Dec 30 '22 03:12

Frank van Puffelen