Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Admin SDK with limited privileges on Firestore?

I have some trouble with Cloud function and firestore rules. I would like use cloud function with limited privilèges on Firestore and give only has access as defined in the Security Rules

It's working without problem on RTDB but not on Firestore.

I have try with this rules

service cloud.firestore {
  match /databases/{database}/documents {

    match /init/{ID=**} {
        allow read, write: if true;
    }

    match /test/{ID=**} {
        allow read, write: if false;
    }
  }
}

And this

const admin = require('firebase-admin');
const functions = require('firebase-functions');
const FieldValue = require('firebase-admin').firestore.FieldValue;

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: 'https://******.firebaseio.com',
    databaseAuthVariableOverride: {
        uid: 'my-worker',
    },
});

const db = admin.firestore();

exports.onTestRights = functions.firestore
    .document('init/{initID}')
    .onCreate((event) => {
        const initID = event.params.initID;
        return db.collection('test').doc(initID).set({'random key': 'random value'}).then(()=>{
            console.log('working');
            return;
        }).catch((err) =>{
            console.log('error: ', err);
            return;
        });
    });

But it's still writing so whereas it should be "permission denied"

Anyone know if it's normal(or not yet implanted) on firestore or I have misunderstood something ?

Edit: Of course my final goal is not with this rules, but only give write/read access on some documents/collections using (allow read, write: if request.auth.uid == 'my-worker';)

Edit2: I would like use the security rules for checking like a transaction if no change during process using this model

like image 317
aTo Avatar asked Nov 02 '17 16:11

aTo


People also ask

Does firebase Admin bypass rules?

1. Admin SDK bypasses security rules. As you explore security rules in depth, you will eventually discover that requests from the Firebase Admin SDK are not gated by rules. The Admin SDK is initialized with a service account, which gives the SDK full access to your data.

What is firestore Admin SDK?

The Admin SDK is a set of server libraries that lets you interact with Firebase from privileged environments to perform actions like: Read and write Realtime Database data with full admin privileges.

Can I use firestore without authentication?

To be honest, without Firebase Authentication, it's not possible to accept writes to a database without Authentication and also avoid abuse, since anyone could write anything from anywhere on the internet. This could also cost you large amounts of money if someone discovers your "open" database.

Can I use firebase Admin client side?

The Firebase Admin SDK should only be run in a privileged environment, like your server or Firebase Cloud Functions. It provides direct administrative access that is not secure on the client.


1 Answers

As you've noticed databaseAuthVariableOverride only works for the Realtime Database. There is nothing right now that allows you to do the same for Firestore in the Admin SDK.

One workaround you could use if you want to limit the access rights on your server code is to use the Client JS SDK rather than Firebase Admin and sign the user-in using a custom token. Here is a sample code to do this:

// Configure Firebase Client SDK.
const firebase = require('firebase/app');
require('firebase/auth');
require('firebase/firestore');
firebase.initializeApp({
  // ... Initialization settings for web apps. You get this from your Firebase console > Add Firebase to your web app
});

// Configure Firebase Admin SDK.
const admin = require('firebase-admin');
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

// Create Custom Auth token for 'my-worker'.
const firebaseReady = admin.auth().createCustomToken('my-worker').then(token => {
  // Sign in the Client SDK as 'my-worker'
  return firebase.auth().signInWithCustomToken(token).then(user => {
    console.log('User now signed-in! uid:', user.uid);

    return firebase.firestore();
  });
});

// Now firebaseReady gives you a Promise that completes with a authorized firestore instance. Use it like this:

exports.onTestRights = functions.firestore
  .document('init/{initID}')
  .onCreate(event => {
    const initID = event.params.initID;
    return firebaseReady.then(db => db.collection('test').doc(initID).set({'random key': 'random value'}).then(() => {
      console.log('working');
      return;
    }).catch((err) =>{
      console.log('error: ', err);
      return;
    });
  );
});
like image 126
Nicolas Garnier Avatar answered Sep 28 '22 14:09

Nicolas Garnier