Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firestore admin in Node.js Missing or insufficient permissions

I am trying to access Firestore using Firebase Admin on Node.js v8.4.0 in a Firebase Cloud Function running locally using firebase functions:shell on Windows 10.

firebase -v 4.2.1

  "dependencies": {
    "firebase-admin": "^6.0.0",
    "firebase-functions": "^2.0.5"
  }

After attempting to use firebase admin from my apps code, I attempted to run the quick start example in https://github.com/firebase/functions-samples/blob/master/quickstarts/uppercase-firestore/functions/index.js.

This is the actual code run:

'use strict';

// [START all]
// [START import]
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');

// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');

admin.initializeApp({})
// [END import]

// [START addMessage]
// Take the text parameter passed to this HTTP endpoint and insert it into the
// Realtime Database under the path /messages/:documentId/original
// [START addMessageTrigger]
exports.addMessage = functions.https.onRequest((req, res) => {
// [END addMessageTrigger]
  // Grab the text parameter.
  const original = req.query.text;
  // [START adminSdkAdd]
  // Push the new message into the Realtime Database using the Firebase Admin SDK.
  return admin.firestore().collection('messages').add({original: original}).then((writeResult) => {
    // Send back a message that we've succesfully written the message
    return res.json({result: `Message with ID: ${writeResult.id} added.`});
  });
  // [END adminSdkAdd]
});
// [END addMessage]

// [START makeUppercase]
// Listens for new messages added to /messages/:documentId/original and creates an
// uppercase version of the message to /messages/:documentId/uppercase
// [START makeUppercaseTrigger]
exports.makeUppercase = functions.firestore.document('/messages/{documentId}')
    .onCreate((snap, context) => {
// [END makeUppercaseTrigger]
      // [START makeUppercaseBody]
      // Grab the current value of what was written to the Realtime Database.
      const original = snap.data().original;
      console.log('Uppercasing', context.params.documentId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an 'uppercase' sibling in the Realtime Database returns a Promise.
      return snap.ref.set({uppercase}, {merge: true});
      // [END makeUppercaseBody]
    });
// [END makeUppercase]
// [END all]

However, I still get the permission denied error.

This is the output I get:

firebase > makeUppercase({original:'alphabets'},{params:{documentId:'mydoc'}})
'Successfully invoked function.'
firebase > info: User function triggered, starting execution
info: Uppercasing mydoc alphabets
info: Function crashed
info: { Error: 7 PERMISSION_DENIED: Missing or insufficient permissions.
    at Object.exports.createStatusError (C:\projects\myproject\functions\node_modules\grpc\src\common.js:87:15)
    at Object.onReceiveStatus (C:\projects\myproject\functions\node_modules\grpc\src\client_interceptors.js:1188:28)
    at InterceptingListener._callNext (C:\projects\myproject\functions\node_modules\grpc\src\client_interceptors.js:564:42)
    at InterceptingListener.onReceiveStatus (C:\projects\myproject\functions\node_modules\grpc\src\client_interceptors.js:614:8)
    at callback (C:\projects\myproject\functions\node_modules\grpc\src\client_interceptors.js:841:24)
  code: 7,
  metadata: Metadata { _internal_repr: {} },
  details: 'Missing or insufficient permissions.' }

My security rules are completely open but that did not resolve the error.

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write;
    }
  }
}

I also thought that this might be an authentication issue so I have tried the following to initialize the app:

1

admin.initializeApp()

2

admin.initializeApp(functions.config().firebase);

3

var serviceAccount = require('path/to/serviceAccountKey.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: 'https://<DATABASE_NAME>.firebaseio.com'
});

The last one with my own credentials file and project configuration. All of these attempts still give me the missing permissions error.

Update: I deployed these functions to the cloud and they seem to be working perfectly but when running locally, I'm still getting a Error:7 Permission Denied.

Update 2: Set application default credentials using gcloud auth application-default login as per suggestion by @Doug Stevenson. Ensured environment variable GOOGLE_APPLICATION_CREDENTIALS is not set. Attempted the code in 1,2 and 3 above as well as 4 below with no success. Encountered the same error.

4

admin.initializeApp({
    credential: admin.credential.applicationDefault(), 
    databaseURL: "https://myapp-redacted.firebaseio.com"
  });
like image 396
smartexpert Avatar asked Sep 06 '18 15:09

smartexpert


1 Answers

I had the same issue and was resolved by going to the cloud console then granting the role Firebase Admin SDK admin service agent to the app engine service account which is in the following format {PROJECT_ID}@appspot.gserviceaccount.com.

like image 61
Hatem Avatar answered Oct 05 '22 10:10

Hatem