This error message occurs when a Firestore Trigger in Firebase Cloud Functions encounters a Permissions issue: Error code 7 PERMISSION_DENIED due to

I've been working on integrating a Firebase Cloud Function to update a document in my Firestore database whenever another document is updated. The trigger is functioning correctly, but I'm encountering an error when trying to access the other document using the firebase admin instance for updating.

Error: 7 PERMISSION_DENIED: Missing or insufficient permissions.
    at Object.exports.createStatusError (/user_code/node_modules/firebase-admin/node_modules/grpc/src/common.js:87:15)
    at ClientReadableStream._emitStatusIfDone (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client.js:235:26)
    at ClientReadableStream._receiveStatus (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client.js:213:8)
    at Object.onReceiveStatus (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client_interceptors.js:1256:15)
    at InterceptingListener._callNext (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client_interceptors.js:564:42)
    at InterceptingListener.onReceiveStatus (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client_interceptors.js:614:8)
    at /user_code/node_modules/firebase-admin/node_modules/grpc/src/client_interceptors.js:1019:24

Function code:

import * as functions from "firebase-functions";
import * as admin from "firebase-admin";

admin.initializeApp();
const settings = { timestampsInSnapshots: true };
admin.firestore().settings(settings);

export const onDocUpdate = functions.firestore
  .document("documents/{documentId}")
  .onUpdate((snapshot, context) => {
    console.log("onDocUpdate called ", context.params.documentId);
    const document = snapshot.after.data();
    console.log("Document: ", document);
    if (document.screw) {
      console.log("Document screw exists. ", document.screw);
      const docRef = admin
        .firestore()
        .collection("screws")
        .doc(document.screw);
      return docRef
        .get()
        .then(doc => {
          if (doc.exists) {
            console.log("Screw for document exists.");
          } else {
            console.error(
              "Screw for document not found! ",
              document.screw
            );
          }
        })
        .catch(error => {
          // Here I get the permission error :(
          console.error(
            "Screw for document doc load error!! ",
            error
          );
        });
    } else {
      console.error("Document is not bound to a screw! ", document.id);
    }
    return null;
  });

package.json

{
  "name": "functions",
  "scripts": {
    "lint": "tslint --project tsconfig.json",
    "build": "tsc",
    "serve": "npm run build && firebase serve --only functions",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "main": "lib/index.js",
  "dependencies": {
    "@google-cloud/firestore": "^0.16.0",
    "firebase-admin": "^6.0.0",
    "firebase-functions": "^2.0.4",
    "protobufjs": "^6.8.8"
  },
  "devDependencies": {
    "tslint": "~5.8.0",
    "typescript": "~2.8.3"
  },
  "private": true
}

I suspect that the issue may be related to permissions of the admin instance, but I'm unsure about what could be causing this error. I have followed the documentation and tutorials provided by Firebase without success.

Although my account is still on a Free Plan, I am receiving a notification in the logs suggesting that I configure a billing account. However, according to the documentation, I should be able to access Google Cloud Platform services and read nodes within the same database without any issues.

I have come across similar issues on Stack Overflow but have not yet found a solution. Perhaps someone else has encountered and resolved this issue since then?

PERMISSION_DENIED Firestore CloudFunction TypeScript and Firebase error writing to Firestore via a Function: "7 PERMISSION_DENIED: Missing or insufficient permissions"

Update 1: I had another problem with the new timestampsInSnapshots setting, which has been resolved and the code above has been updated. However, the main issue of permission denied still persists.

Update 2: In response to the answer given by @RonRoyston below, this is a Cloud Function utilizing the Admin SDK from the firebase-admin package to access the node. Thus, it should not be affected by Firestore security rules. There is already a comment on one of the linked questions by @DougStevenson highlighting this. Based on the Admin SDK documentation, initializing it by calling admin.initializeApp() should suffice, but unfortunately, it does not seem to work in my case. I have not come across any information stating the need for special IAM settings within service accounts or security rules when using Cloud Functions, so I have not made any adjustments to these settings.

Cheers, Lars

Answer №1

I encountered a similar issue and, like exampleuser, I was able to resolve it by adjusting permissions.

When I created a function, I noticed that the default service account was set to

<project-name>@appspot.gserviceaccount.com
.

You can confirm this by accessing the

Environment variables, networking, timeouts, and more
link:

From there, make sure to verify or change the account to the 'App Engine default service account':

Next, I checked the IAM to review the permissions assigned to this service account.

However, the IAM did not have the service account listed in its records.

To address this, I added the service account by going to >> Add >> New members. By entering the project ID, the service account should appear in the drop-down for selection.

Subsequently, I granted the following permissions:

  • Project >> Editor (It may already have this)
  • Datastore >> Cloud Datastore Owner
  • Storage >> Storage Admin

I hope this solution proves beneficial to you as well.

Answer №2

To solve the issue, I took the necessary steps to set up the serviceAccount. Here's a snippet of the code that worked for me:

const admin = require("firebase-admin");

const serviceAccount = require("path/to/serviceAccountKey.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://your-database-url.firebaseio.com"
});

If you're not sure how to generate the serviceAccountKey, you can do so by accessing: Firebase dashboard -> Project Settings -> Service Accounts tab

I hope this solution proves helpful!

Answer №3

Dealing with Cloud Functions also presented a challenge for me. Simply deleting or redeploying the function did not resolve my issue. Upon further investigation, I discovered that the IAM roles for the default service account were not properly configured when my project was set up. To rectify this, I had to manually assign an Editor role in the IAM Admin panel for

<project-name>@appspot.gserviceaccount.com
.

Answer №4

After some troubleshooting, I managed to fix the issue. Surprisingly, I didn't need to make any changes to my firestore security rules or IAM settings. What did the trick was deleting the function that was originally running on us-central1 and then recreating the Cloud Function project in europe-west1. Simply copying over my existing code and redeploying it worked like a charm this time.

I suspect that there may have been a glitch during the initial deployment to us-central1, causing my project to get stuck with the error even after multiple attempts at deletion and redeployment. It's puzzling because no clear errors were being displayed. Perhaps someone from the firebase team with knowledge of internal workflows can shed light on whether these kinds of issues can arise, and if so, how to resolve them.

Fortunately, following the steps outlined above resolved my problem for now.

Answer №5

I encountered a similar error and after searching extensively, I couldn't find a solution. So, I decided to share my experience here in case it might help someone else...

We operate with two separate firebase projects; one for development (DEV) and the other for production (PROD). The PERMISSION_DENIED issue can also arise if you mistakenly specify the wrong projectId in the following line of code:

admin.initializeApp({projectId: 'your_project_id'});

Answer №6

Here's a solution that successfully resolved my issue:

  • My problem arose from switching between different Firebase projects in order to test a Cloud Function and observe the results in production within Firestore. Despite having the Cloud Function set up to create data in production Firestore for one project (e.g., "project-dev"), I consistently encountered a permission denied error when attempting to create new documents via the cloud function using the downloaded serviceAccount credentials for another project ("project-sandbox").
let serviceAccount = require('../credentials-sb.json');
admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://<project>-sandbox.firebaseio.com"
});
  • I realized that I had not yet utilized the firebase use command for the new project, nor had I added it to .firebaserc file. Essentially, I was operating under a different project setting than what the credentials file required. After running firebase use project-sandbox, followed by npm run shell to execute my function from the emulator, everything functioned seamlessly. The emulator served its purpose correctly for both "project-sandbox" and "project-dev".

It is likely that this was due to defining a project-id environment variable automatically detected during the execution of admin.initializeApp(), or alternatively, could have been manually set as demonstrated below:

let serviceAccount = require('../credentials-sb.json');
admin.initializeApp({
    project-id: '<project>-sandbox'
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://inkling-sandbox.firebaseio.com"
});

I trust that these insights are beneficial! Feel free to share your feedback on the outcome.

Answer №7

A quick and effective fix that solved the issue for me was executing these commands:

firebase login //login using browser with project account
firebase init firestore //When prompted, choose the firebase project

I made sure to run this in the same directory where I set up the project initially.

Important Note: Always select No when it asks about overwriting any files.

Additional Tip: This approach resolved my local functions not functioning properly after transferring the project between machines. Reinitializing the project proved to be the solution when nothing else worked.

Answer №8

After encountering issues with my service account, I decided to recreate it from scratch and then redeploy it.

Answer №9

By creating a new service account, I was able to resolve this issue efficiently.

  1. To resolve the issue, I created a new service account in IAM.
  2. Next, I assigned the roles 'Cloud Datastore User' and 'Firebase Rules Viewer' to the new service account in IAM.
  3. Finally, I edited the function details in Cloud Functions and configured it to use the new service account.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can you explain the correct method for assigning types when destructuring the `callbackFn.currentValue` in conjunction with the `.reduce()` method? Thank you

I'm working with an array of arrays, for example: const input = [['A', 'X'], ['B', 'Y'],...]; In addition to that, I have two enums: enum MyMove { Rock = 'X', Paper = 'Y', Scis ...

In Certain Circumstances, Redirects Are Applicable

I have set up Private Routing in my project. With this configuration, if there is a token stored in the localStorage, users can access private routes. If not, they will be redirected to the /404 page: const token = localStorage.getItem('token'); ...

Different ways to reference a variable in Typescript without relying on the keyword "this" throughout the codebase

Can we eliminate the need to write "this" repeatedly, and find a way to write heroes, myHero, lastone without using "this"? Similar to how it is done in common JavaScript. https://i.stack.imgur.com/TZ4sM.png ...

Strategies for Handling Errors within Observable Subscriptions in Angular

While working with code from themes written in the latest Angular versions and doing research online, I've noticed that many developers neglect error handling when it comes to subscription. My question is: When is it necessary to handle errors in an ...

The 'picker' property is not found in the '{}' type but is necessary in the 'TimeRangePickerProps' type

I am encountering an issue while trying to implement the new RangePicker for the TimePicker of antd v4. Surprisingly, this error only occurs in my development environment and not when I try to reproduce it on codesandbox. Despite checking their documentati ...

Turn TypeScript - Modify type properties to reflect types of their descendants

I am currently working on creating a type that will modify a generic type based on its children. To provide some clarity, I have created a simplified example below: Original type type FormFields = { username: { type: string, ...

Error in Typescript: Cannot find reference to @viewChild

I attempted to use the select() method in tabs.ts based on the Ionic Tabs documentation. However, upon running it, I encountered an error stating that "select is undefined". Upon further investigation, I realized that my viewChild was empty or undefined wh ...

Is there a way for me to retrieve the value that has been set within the cy.get() function in Cypress using Typescript?

Is there a way to retrieve the value of the getLength function without it returning undefined? How can I access the value in this case? Here is my code snippet: const verifyValue = () => { const selector = 'nz-option-container nz-option-item&apo ...

Is it possible to retrieve information from the parent in a Cloud Function?

How can I properly assign the name value inside the parent to a const? exports.myFunction = functions.database.ref('/messages/{pushId}/likes') .onWrite(event => { const name = event.parent.data.val().name; // This approach doesn't ...

Combine two elements in an array

I am faced with a challenge in binding values from an Array. My goal is to display two values in a row, then the next two values in the following row, and so on. Unfortunately, I have been unable to achieve this using *ngFor. Any assistance would be greatl ...

"Seeking guidance on getting my carousel functionality up and running in Angular 8 - any

I tried implementing a carousel from the Bootstrap 4 documentation, but it is only displaying one image. How can I modify the carousel to show all images? I am new to using Angular. Below is the code I have: <div class=" bg-success text-white py-5 tex ...

What is the best way to assign a value to an undefined or null property in a Firebase object

Is there a way to set null or undefined as a value in a Firebase object like the code snippet below? const updateObject: Partial<SomeObject> = { name: "new name", age: undefined } userPlanReference.update(updateObject); After runn ...

Make sure to verify the status of ngmodel or forms to see if they are dirty or contain

In Angular, how can I determine if ngModel or form fields are dirty or have input without using formgroup? I need to check if at least 5 of the input fields have a value or are considered dirty in order to display a message. How can I achieve this for 5 f ...

Displaying images in Ionic from a JSON URL source

I am having trouble getting an image from a JSON to display on an Ionic card. Although I can see the JSON response in the console log, the image is not showing up on the card, leaving it blank. It seems like I'm making a mistake in the HTML code. Any ...

What kind of Antd type should be used for the form's onFinish event?

Currently, I find myself including the following code snippet repeatedly throughout my project: // eslint-disable-next-line @typescript-eslint/no-explicit-any const handleCreate = (input: any): void => { saveToBackend({ title: input.title, oth ...

Managing time in an Angular application using Typescript

I am facing an issue with formatting the time obtained from an API in my FormArray. The time is received in the format: 14.21.00 My goal is to convert this time to the following format: 2:21 PM I have attempted to format it using Angular's DatePip ...

Troubleshooting MeshStandardMaterial problem in Three.js on Mac M1 with Chrome

Having an issue on my M1 Mac with Chrome, where my scene appears like https://i.sstatic.net/tWckT.png. However, it looks fine in Safari or Firefox https://i.sstatic.net/9TJvQ.png The problem seems to be related to the rendering of walls. Here is my code: ...

Observing the completion of a subscriber function

Is there a more streamlined way to determine if the subscriber has finished executing or return something and catch it up-stream? Consider the following code snippets: this._subscriptions.push(this._client .getCommandStream(this._command) // R ...

Steps for updating text within an object in Angular

details = [ { event: "02/01/2019 - [Juan] - D - [Leo]", point: 72 }, { event: "02/01/2019 - [Carlo] - N - [Trish]", point: 92 } ]; I am attempting to modify the text within the titles that contain - N - or - D - The desired outcom ...

The 'required' validator in Mongoose seems to be malfunctioning

I've been attempting to validate the request body against a Mongoose model that has 'required' validators, but I haven't been successful in achieving the desired outcome so far. My setup involves using Next.js API routes connected to Mo ...