0

I'm getting a 403 SignatureDoesNotMatch error when trying to load a url generated through:

file.getSignedUrl({
  expires: moment()
    .add(10, 'minutes')
    .format()
})

I've done all the steps outlined in the example, including adding a service account token creator to the App Engine default service account to allow the creation of signed urls:

enter image description here


As an alternative approach to using admin via firebase-functions I tried downloading service account credentials service-account-credentials.json and creating a gcs storage object as suggested here as such:

const { Storage } = require('@google-cloud/storage');
const storage = new Storage({
  keyFilename: 'service-account-credentials.json',
  projectId: 'project-id',
});

storage.bucket('bucket-id').getFiles({prefix: 'path/to/dir'}).then(files => files.map(file => [same code as above]));

However this still generates SignatureDoesNotMatch urls.


I've followed the github issue related to the matter but I have not been able to find a viable solution. The solution listed by Firebase dev owner @mcdonamp in the issue references using iam.signBlobRequest but I don't know where iam is defined, I only see it here as a property of bucket, with no signBlobRequest method, and here as an HTTP API endpoint.

Dane Jordan
  • 1,071
  • 1
  • 17
  • 27

1 Answers1

1

Seems that despite the doc's claim of Content-Type headers being optional, they are not. As suggested by this SO post and this github issue, adding contentType to the getSignedUrl options argument fixes the issue:

file.getSignedUrl({
  action: 'read',
  contentType: 'audio/wav',
  expires: moment()
  .add(10, 'minutes')
  .format()
})

Make sure to also include the header when requesting the resource as well.

Dane Jordan
  • 1,071
  • 1
  • 17
  • 27