firebase-tools: Invalid-credential error for admin.auth calls

Getting the Following Error when using initializeApp() within the functions emulator without a credentials file. This worked before on firebase-tools@6.8.0. Has this behaviour changed between 6.8.0 and 6.11.0? If yes, why isn’t it within the changelogs? The docs actually say now that

All other APIs, including Firebase APIs such as Authentication and FCM or Google APIs such as Cloud Translation or Cloud Speech, require the setup steps described in this section. This applies whether you’re using the functions shell or firebase serve.

Still wondering why it wasn’t necessary in firebase-tools@6.8.0

Related issues

#1299 seems related, but I am using firebase serve instead of firebase emulators:start

Environment info

firebase-tools: 6.11.0 Platform: macOSX 10.14.5 Node: 10.15.3 (but ocurring with 8.14.0 as well) firebase-functions: 2.3.1 firebase-admin: 8.0.0

Test case

A freshly generated firebase project using firebase init with functions. Install firebase-admin@8.0.0 and firebase-functions@2.3.1. Make sure you are running the latest firebase-tools@6.11.0. Run npm install --save grpc to prevent #1341.

Use Node 10.15.3 or 8.14.0 and change the package.json engines node to 10 or 8 respectively.

Than edit the functions/index.js file copying and pasting the below:

const functions = require( 'firebase-functions' );
const admin     = require( 'firebase-admin' );

admin.initializeApp();

exports.login = functions.https.onRequest( async ( req, res ) => {

    var users = await admin.auth().listUsers();

    res.json( users );

} );

Steps to reproduce

Run firebase serve within the newly created project as described above. Than make a request to the exported /login endpoint. The error will be thrown in the terminal console.

Expected behavior

No error should be thrown. The emulator should automatically have sufficient credentials to use firebaseAdmin.auth() methods.

Actual behavior

Your code has been provided a "firebase-admin" instance.
⚠  Error: Credential implementation provided to initializeApp() via the "credential" property failed to fetch a valid Google OAuth2 access token with the following error: "Error fetching access token: invalid_grant (Token has been expired or revoked.)". There are two likely causes: (1) your server time is not properly synced or (2) your certificate key file has been revoked. To solve (1), re-sync the time on your server. To solve (2), make sure the key ID for your key file is still present at https://console.firebase.google.com/iam-admin/serviceaccounts/project. If not, generate a new key file at https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk.
    at FirebaseAppError.FirebaseError [as constructor] (/Applications/MAMP/htdocs/debug/functions/node_modules/firebase-admin/lib/utils/error.js:42:28)
    at FirebaseAppError.PrefixedFirebaseError [as constructor] (/Applications/MAMP/htdocs/debug/functions/node_modules/firebase-admin/lib/utils/error.js:88:28)
    at new FirebaseAppError (/Applications/MAMP/htdocs/debug/functions/node_modules/firebase-admin/lib/utils/error.js:122:28)
    at /Applications/MAMP/htdocs/debug/functions/node_modules/firebase-admin/lib/firebase-app.js:121:23
    at process._tickCallback (internal/process/next_tick.js:68:7)

If I downgrade back to firebase-tools@6.8.0 it works.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Comments: 19 (7 by maintainers)

Most upvoted comments

This is still happening for me, and is pretty annoying. Everything else works with ADC (GCE, Firestore, GCS, etc.) but for some reason auth doesn’t, and this is considered to be “working as intended”. I can’t always set GOOGLE_APPLICATION_CREDENTIALS because that confuses some other things that need to use application-default credentials. So I’m forced to set it and unset it depending on which of my local admin tools I’m using! It’s even more annoying because when I switch projects from dev to production it’s just one more thing to have to remember to switch, and if it’s silently out of sync from gcloud config get-value project then I can accidentally update the wrong dataset.

Yes. Try the test case above. It works with 7.0.0 and fails with this error on 7.0.2

Error: //developers.google.com/identity/sign-in/web/devconsole-project. Raw server response: "{"error":{"code":401,"message":"Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.","errors":[{"message":"Invalid Credentials","domain":"global","reason":"authError","location":"Authorization","locationType":"header"}],"status":"UNAUTHENTICATED"}}"
    at FirebaseAuthError.FirebaseError [as constructor] (/Applications/MAMP/htdocs/debug/functions/node_modules/firebase-admin/lib/utils/error.js:42:28)
    at FirebaseAuthError.PrefixedFirebaseError [as constructor] (/Applications/MAMP/htdocs/debug/functions/node_modules/firebase-admin/lib/utils/error.js:88:28)
    at new FirebaseAuthError (/Applications/MAMP/htdocs/debug/functions/node_modules/firebase-admin/lib/utils/error.js:146:16)
    at Function.FirebaseAuthError.fromServerError (/Applications/MAMP/htdocs/debug/functions/node_modules/firebase-admin/lib/utils/error.js:185:16)
    at /Applications/MAMP/htdocs/debug/functions/node_modules/firebase-admin/lib/auth/auth-api-request.js:1139:49
    at process._tickCallback (internal/process/next_tick.js:68:7)

I don’t know if anyone else is dumb enough to try what I did,

But I fixed this issue by going to the Firebase console and creating a Service account from there instead of creating a Service account from the GCP IAM & Admin area. Then I initialized the project with:

var serviceAccount = require('./myproject-1234.json');

admin.initializeApp({
    projectId: 'myproject',
    credential: admin.credential.cert(serviceAccount),
});

To help narrow the search, 7.0.1 doesn’t throw this error for me.

@jaschaio while the error you got is not related to what I am about to say, it was actually protecting you from another more serious error. And fixing one will fix both, so let’s just jump to that.

Ok so when you run admin.initializeApp() it does this process to search for credentials: https://cloud.google.com/docs/authentication/production#finding_credentials_automatically

When you’re running in Cloud Functions it finds a service account and everything is great. When you’re running locally it finds the credential you probably set up with gcloud auth application-default login which is a user credential that has a Client ID that points to the shared gcloud project. You don’t have to care about that detail at all. However if you do try and use that credential to run admin.auth().listUsers() you will get an error like this one:

Error: //cloud.google.com/docs/authentication/. Raw server response: "{"error":{"code":403,"message":"Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the identitytoolkit.googleapis.com. We recommend that most server applications use service accounts instead. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.","errors":[{"message":"Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the identitytoolkit.googleapis.com. We recommend that most server applications use service accounts instead. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.","domain":"usageLimits","reason":"accessNotConfigured","extendedHelp":"https://console.developers.google.com"}],"status":"PERMISSION_DENIED"}}"

So the way to solve this is to make sure you set GOOGLE_APPLICATION_CREDENTIALS and point it to a service account JSON file for your project.

So you’d do:

GOOGLE_APPLICATION_CREDENTIALS=your_service_account.json firebase serve

Note that this is specific to the Auth API. You’ll notice that the Firestore API accepts these “user credentials” without any complains. Both APIs consider this situation “working as intended” and for now there is nothing we can do to work around it in the emulator.

I hope that makes sense!