3
votes

Cloud Function gets a firebase permission denied error when updating or removing.

The service account is initialized with credentials from a file in order to use auth.createCustomToken which isn't currently available for the default account

admin = require('firebase-admin');
functions = require('firebase-functions');
credential = admin.credential.cert(require('./credentials.json'));
admin.initializeApp({credential: credential, databaseURL: functions.config().firebase.databaseURL});

The security rules that prevent the updates:

"downloads": {
  "$key": {
    ".write": "data.val() == null"
  }
}

The user inserts data with push into /downloads then Cloud Function tries to update and subsequently remove. Both of these operations fail even though admin accounts supposedly bypass all security rules including validation.

FIREBASE WARNING: update at /downloads/-Kexz33ljYjKblF_ZgUo failed: permission_denied
FIREBASE WARNING: set at /downloads/-Kexz33ljYjKblF_ZgUo failed: permission_denied

The first error (update) disappears if I change the rules to this:

"downloads": {
  "$key": {
    ".write": "newData.child('uid').val() == auth.uid"
  }
}

UPDATE

The workaround is to redefine event.data.ref to be

ref = admin.database().ref(event.data.ref.path.toString())
1
Can you edit your question to include the code that triggers the permission_denied?Frank van Puffelen

1 Answers

15
votes

Within the event.data object returned to your Cloud Function's onWrite() callback, there are two types of Database references: one that is scoped to to the same permissions as the user who triggered the write (event.data.ref) and one that is scoped with admin rights, granting full read and write access (event.data.adminRef). I can't tell since you didn't provide a code sample showing your Cloud Function, but I bet you are using event.data.ref. Switching to use event.data.adminRef should resolve your problem.