5

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

aTo
  • 285
  • 3
  • 16

1 Answers1

8

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;
    });
  );
});
Nicolas Garnier
  • 12,134
  • 2
  • 42
  • 39
  • Your sample is not working, I have this error (https://pastebin.com/K5Bk7fRF). After look on Google i found it's because `require('firebase/firestore');` is needed. So i add it with the needed dependency (grpc and protobufjs) via npm install and i get another error: https://pastebin.com/gUCTu1Sh – aTo Nov 08 '17 at 15:50
  • Looks like your last issue happens for people using protobufjs v6. Can you try adding protobufjs v5 as a dependency instead? – Nicolas Garnier Nov 08 '17 at 22:06
  • And FYI as you pointed out https://github.com/firebase/firebase-js-sdk/issues/221 indicates that Firestore does not work on NodeJS. So we migth get stuck in the end but let's see if we can find workarounds to make it work anyways :) – Nicolas Garnier Nov 08 '17 at 22:07
  • I'm afraid of it... Do you know if this feature is planned ? I will try to see if can use some transaction for make it work my app partially in the meantime. – aTo Nov 09 '17 at 18:03
  • 1
    This feature is on the roadmap (we want to build it) but we don't have a timeframe we can share yet... – Nicolas Garnier Nov 09 '17 at 22:36
  • 1
    @Nivco With latest release this is now working. But please note bug in sample code posted, missing return statement, should be "return firebase.auth().signInWithCustomToken..." Thanks – Greg Ennis Dec 04 '17 at 15:45
  • @NicolasGarnier I've now seen at least 3 SO questions for this. I appreciate you providing this 'hack', it makes sense. Anywhere we can upvote this feature? – Nth.gol Aug 10 '18 at 13:04
  • 1
    I get `serviceAccount is undefined` where is this set? And what does it contain? – Gerardlamo May 18 '19 at 08:39