'Google storage permissions error while generating signed url from cloud function

I'm attempting to use a Firebase Cloud Function to create signed download URLs for files stored in a Storage Bucket. Using the snippet below on my local machine, I'm able to access cloud storage and generate these URLs.

/* eslint-disable indent */
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const serviceAccount = require("./test-serviceAccount.json");

admin.initializeApp();
const storage = admin.storage();
const bucket = storage.bucket();

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
}, "firestore");

export const getFile = functions.https.onRequest(async (request, response) => {
  const [files] = await bucket.getFiles();
  const fileNames: string[] = [];
  files.forEach(async (file) => {
    console.log(file.name);
    const url = await file.getSignedUrl(
      {
        version: "v2",
        action: "read",
        expires: Date.now() + 1000 * 60 * 60 * 24,
      }
    );
    fileNames.push(String(url));
    if (files.indexOf(file) === files.length - 1) {
      response.send(JSON.stringify(fileNames));
    }
  });
});

However after deploying to Cloud Functions I get an error when I call the function saying:

Error: could not handle the request

and the following message is logged in the functions console:

Error: The caller does not have permission
    at Gaxios._request (/workspace/node_modules/gaxios/build/src/gaxios.js:129:23)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at async Compute.requestAsync (/workspace/node_modules/google-auth-library/build/src/auth/oauth2client.js:368:18)
    at async GoogleAuth.signBlob (/workspace/node_modules/google-auth-library/build/src/auth/googleauth.js:655:21)
    at async sign (/workspace/node_modules/@google-cloud/storage/build/src/signer.js:97:35) 

I've tried using and not using a .json service account key and made sure that the service account has permissions (it has Service Account Token Creator, Storage Admin, and Editor roles at the moment).

I also read this issue relating to the python SDK for storage, but it seems to have been resolved. The workaround mentioned in that issue (using a .json service account token) also didn't resolve the permissions errors.



Solution 1:[1]

After working with Firebase support - here's what worked for me:

import { initializeApp, applicationDefault } from 'firebase-admin/app';

initializeApp({
 credential: applicationDefault(),
 projectId: '<FIREBASE_PROJECT_ID>',
});

Specifying the projectId in the init call seems to have resolved the issue.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Todd Rylaarsdam