Firebase-tools: Firebase Cloud Functions: app/invalid-credential failed to fetch a valid Google OAuth2 access token Firebase Admin SDK

Created on 9 Oct 2019  ·  38Comments  ·  Source: firebase/firebase-tools

[REQUIRED] Environment info


firebase-tools: 7.5.0


Platform: macOS

[REQUIRED] Test case

[REQUIRED] Steps to reproduce

I am new to Cloud Functions. I followed the docs, and the new initialization syntax for firebase-admin, but I am getting an auth error when running the function on the server and on a localhost.

https://firebase.google.com/docs/functions/beta-v1-diff#new_initialization_syntax_for_firebase-admin

@firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"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: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal. Error code: ENOTFOUND\"."}

I tried instantiating the sdk with a serviceAccountKey, same issue. https://firebase.google.com/docs/admin/setup#initialize_the_sdk

The function is being triggered on localhost and on the server, and error is being thrown once the call to the database is being made at gettingUser()

When running locally after building:

$ firebase experimental:functions:shell
firebase > const data = {some_article...}
firebase > addingNewArticle(data)
'Successfully invoked function.'
firebase > >  New article created articleId1

DEBUG: @firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"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: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal. Error code: ENOTFOUND\"."}

/index.ts

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

admin.initializeApp();

export const addingNewArticle = functions.database
.ref('/articles/{articleId}')
.onCreate(async (snapshot, context) => {
  const articleId = context.params.articleId

  const result = await gettingUser();
  console.log(`From onCreate ${result}`);


  console.log(`New article created ${articleId}`)

  const articleVal = snapshot.val()
  const name = articleVal.name
  const addedById = articleVal.addedById

  console.log(`${name} was added by: ${addedById}`);
  console.log(`burgersVal: ${articleVal}`);
  console.log(`snapshot: ${snapshot}`);


  return Promise.all([])
})


export async function gettingUser() {
    const result = await admin.database().ref(`users/fnkjasdfadsfna.d`).once('value');
    console.log(`Looging new user ${result.val()}`);
    return result.val()
}
functions functions

Most helpful comment

To anyone experiencing this issue:

  • If you're seeing it in the emulator you can fix it by either setting GOOGLE_APPLICATION_CREDENTIALS to a service account or running gcloud auth application-default login on your machine.
  • If you're seeing this in production contact Firebase Support immediately, this should never happen.

All 38 comments

This issue does not seem to follow the issue template. Make sure you provide all the required information.

@talezion thanks for filing this! Just to be clear do you want the admin.database() call to use production database or are you trying to use the database emulator?

Hi @samtstern, correct, I am trying to access the production database from the emulator. Actually, I get a similar auth error when running this on the server as well.

This is the error I get on the server:

[2019-09-26T22:14:53.387Z]  @firebase/database: FIREBASE WARNING: Provided authentication credentials for the app named "[DEFAULT]" are invalid. This usually indicates your app was not initialized correctly. Make sure the "credential" property provided to initializeApp() is authorized to access the specified "databaseURL" and is from the correct project. 

@talezion huh so you see this with deployed Cloud Functions as well? Are you initializing anywhere besides admin.initializeApp();? That should use the application default credentials.

Ok so I made a simple function to show me my credentials:

const app = admin.initializeApp();

exports.helloWorld = functions.https.onRequest((request, response) => {
 response.json(app.options);
});

When I call it locally I get something like this:

{
    "credential": {
        "credential_": {
            "httpClient": {
                "retry": {
                    "backOffFactor": 0.5,
                    "ioErrorCodes": [
                        "ECONNRESET",
                        "ETIMEDOUT"
                    ],
                    "maxDelayInMillis": 60000,
                    "maxRetries": 4,
                    "statusCodes": [
                        503
                    ]
                }
            },
            "refreshToken": {
                "clientId": "764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com",
                "clientSecret": "REDACTED",
                "refreshToken": "REDACTED",
                "type": "authorized_user"
            }
        }
    },
    "databaseURL": "https://fir-dumpster.firebaseio.com",
    "projectId": "fir-dumpster",
    "storageBucket": "fir-dumpster.appspot.com"
}

@talezion could you do the same and show me the output? Make sure to hide your clientSecret and refreshToken like I did, those are dangerous to share.

@samtstern I only initialised it as admin.initializeApp();. I also tried different methods as described in https://firebase.google.com/docs/admin/setup#initialize_the_sdk or using a serviceAccountKey.json with no luck.

Thank you for your example. Please see below the output:

firebase > helloWorld()
Sent request to function.
firebase > 
RESPONSE RECEIVED FROM FUNCTION: 200, {
  "databaseURL": "https://<PROJECT-ID>.firebaseio.com",
  "storageBucket": "<PROJECT-ID>.appspot.com",
  "projectId": "<PROJECT-ID>",
  "credential": {
    "credential_": {
      "httpClient": {
        "retry": {
          "maxRetries": 4,
          "statusCodes": [
            503
          ],
          "ioErrorCodes": [
            "ECONNRESET",
            "ETIMEDOUT"
          ],
          "backOffFactor": 0.5,
          "maxDelayInMillis": 60000
        }
      }
    }
  }
}

@talezion ok two things;

1) Did it literally say <PROJECT-ID> or is that your redaction?
2) Huh very strange that it doesn't have a refreshToken ... I'll have to find out how that's possible.

@samtstern

  1. No, I just replaced <PROJECT-ID> with the project id which was correct.
  2. Thanks!

Ok so I think in production that response is normal, but locally I would expect more.

Two things now:
1) Do you have the GOOGLE_APPLICATION_CREDENTIALS environment variable set?
2) Can you try running firebase logout and firebase login again and see if that makes it work better locally?

@samtstern

  1. Yes, I tried setting:
    set GOOGLE_APPLICATION_CREDENTIALS="/functions/src/serviceAccountKey.json".
    Then running shell
  2. Yeah, tried logging out, and logging back in, still same issue

@talezion hmm ok thanks for confirming. To be honest I am totally stumped at the moment but will keep thinking about this.

Thanks @samtstern , I tried to test it on a completely new project and it works.

  1. Created a new project
  2. init functions
  3. executed the same code

It works fine.

Apart from creating a new project, I deleted and initiated a new functions project, and deployed the same code. This is the error I get:

@firebase/database: FIREBASE WARNING: Provided authentication credentials for the app named "[DEFAULT]" are invalid. This usually indicates your app was not initialized correctly. Make sure the "credential" property provided to initializeApp() is authorized to access the specified "databaseURL" and is from the correct project. 

The old project was created in January this year, is there anything that needs to be done on the console?

I have the same problem. Here is my clue:
1.- Start a project and functions, all works fine.
2.- Send to GitHub and open in other computer, make NPM installs, and stills works fine. I worked in this computer all night, I make a PUSH but still works fine.
3.- Return to first computer make pull, and then crash.
4.- Test in second computer, still works fine.

As you see I have same code in two computers, in one of them crash after make a pull request.

The console message said is a credential problem, I tried with this without success:

  • Reset my firebase login in terminal
  • erase the database rules configuration in the local file
  • I use functions credentials, I change them for configuration project
  • Install firebase-tools in the node_modules folder project

i will restart with empty project.

After upgrading to Mac OS Catalina I encountered this issue. What resolved it for me was running the following commands:

  • firebase login
  • export GOOGLE_APPLICATION_CREDENTIALS="<PATH_TO_YOUR_SERVICE_ACCOUNT_KEY_JSON>"

Is there a solution posted somewhere? I am getting this warning today when trying to access a database through an a cloud function running locally.

I have the exact same problem, for the life of me can't figure out what's going on. I tried multiple service account jsons, resetted my project multiple times, rebooted, logged in and out, re set the GOOGLE_APPLICATION_CREDENTIALS variable and even switched OS.
I thought it could be a problem with my windows machine since from there i cannot even start the emulator because it says it lacks a refresh token,
Error: Failed to parse refresh token file: Error: Refresh token must contain a "client_secret" property.

so i did a clean install of Linux and set up the project. The first time it worked ok after setting the service account, but after reboting the linux machine i have the exact same problem back again.
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: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal. Error code: ENOTFOUND".

Here's my options from the cloud function:

{
    "credential": {
        "credential_": {
            "httpClient": {
                "retry": {
                    "maxRetries": 4,
                    "statusCodes": [
                        503
                    ],
                    "ioErrorCodes": [
                        "ECONNRESET",
                        "ETIMEDOUT"
                    ],
                    "backOffFactor": 0.5,
                    "maxDelayInMillis": 60000
                }
            }
        }
    },
    "databaseURL": "https://REDACTED.firebaseio.com"
}

Initialized with:

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
  databaseURL: 'https://REDACTED.firebaseio.com'
});

Same issue here! on my linux desktop works fine. Deployed on EKS (alpine) outputs infinitely:

[2019-12-20T20:28:27.137Z] @firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"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 (Invalid issuer: Not a service account.)\". 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."}

New key has been generated and works locally just fine but again not when deployed on cloud.

Please, did someone fix this?

Same to me
[2019-12-21T11:21:35.790Z] @firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"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: <html>\r\n<head><title>302 Found</title></head>\r\n<body bgcolor=\"white\">\r\n<center><h1>302 Found</h1></center>\r\n<hr><center>nginx/1.14.2</center>\r\n</body>\r\n</html>\r\n\"."}

Same problem as author:

I have followed this reference to initialize my app:

admin.initializeApp({ credential: admin.credential.applicationDefault(), ... })

(actually omitting credential entirely has the exact same result), and fail with following error when running on local machine (not in cloud):

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: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal. Error code: ENOTFOUND"

(funnily the problem pertains to firebase-admin, but this is the first hit on Google, so I thought I'd join the party...)

metadata.google.internal?

Here is the oddest part: it is trying to get a token from some metadata.google.internal domain which sounds like it can only work in a Google Cloud Function? Is local development not supported anymore?

Either way; I debugged a little, and found that it happens in node_modules/firebase-admin/lib/auth/credential.js

which has a big fat:

var GOOGLE_METADATA_SERVICE_HOST = 'metadata.google.internal';

[Here is a link to source]

@samtstern any updates? Why does it try to get tokens from an internal address for everyone?

I also see this while not logged in, and not using a GOOGLE_APPLICATION_CREDENTIALS. I see it happening when running firebase functions:shell and then invoking a onWrite database trigger for Realtime Database. The trigger just returns null and doesn't do anything else.

>  [2020-01-17T20:00:30.997Z]  @firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"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: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal. Error code: ENOTFOUND\"."}

Same problem here, still unsolved.

Same issue as well

The error message is cryptic, but the fix (at least in my case) was simple. As pointed out by @hiranya911 in this related issue, the error occurs if your config/environment variables are not setup correctly, you want to double-check your GOOGLE_APPLICATION_CREDENTIALS specifically.

To anyone experiencing this issue:

  • If you're seeing it in the emulator you can fix it by either setting GOOGLE_APPLICATION_CREDENTIALS to a service account or running gcloud auth application-default login on your machine.
  • If you're seeing this in production contact Firebase Support immediately, this should never happen.

To anyone experiencing this issue:

  • If you're seeing it in the emulator you can fix it by either setting GOOGLE_APPLICATION_CREDENTIALS to a service account or running gcloud auth application-default login on your machine.
  • If you're seeing this in production contact Firebase Support immediately, this should never happen.

Same issue here, but fixed with @samtstern's solution!! Thank you.

Thank you @samtstern. I had this issue due to multiple Google accounts. One was used on Firebase CLI, another was logged into Google Cloud CLI... re-logging into both with the same account solved the issue.
🙌

Can confirm that @samtstern's solution of setting GOOGLE_APPLICATION_CREDENTIALS worked for me.

I'm having trouble using the functions emulator with my realtime database (the real online and not emulated if that is possible).

[2020-03-15T23:36:45.803Z]  @firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"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: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal metadata.google.internal:80. Error code: ENOTFOUND\"."}

I've tried sett the variable export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/[FILE_NAME].json" as in
https://cloud.google.com/docs/authentication/getting-started
Tried both pointing out a defaultAccount.json and a serviceAccount.json.

What could I be doing wrong?

I was also having trouble ( the same Error code: ENOTFOUND\"." error)... even when using samtstern's solution... so, I combined the two solutions; one part being to generate the json.key from google cloud console and one part from this StackOverflow answer.

First part (google cloud console):

  • Select the desired project by clicking at the "Select a project" button at the top of the screen
  • Create a key by going to the "three dots" menu in the row where under "Name" it says "App Engine default service account"
  • this will download a __your_app_sth__.json key file

Second part (SO answer):

  • go to your index.json where your functions are, and at admin.initializeApp() put the data from the generated .json file as formatted in the StackOveflow answer.

Cheers!

Here is how I managed to fix the issue:

Error message:

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 (Bad Request)". 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.

Solution:

Step 1: SYNC the time for local pc with a time server. There was a difference of 1 second in my case, but windows 10 has a SYNC NOW button, used it, and time synced. Checked it on: https://time.is/

Step 2: Go to link https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk above. Generate a private key there. Save it to a folder on your pc. Say "D:\Path\project-101-firebase-adminsdk-cb748-fhry6shja.json". Then on the index.ts file of your functions folder, update the code as follows:

`
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

var serviceAccount = require("D://Path//project-101-firebase-adminsdk-cb748-fhry6shja.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://project-101.firebaseio.com"
});
`

Optional Step: (I am not sure if this is still required) - we can set the GOOGLE_APPLICATION_CREDENTIALS on pc as follows:

set GOOGLE_APPLICATION_CREDENTIALS="D:\Path\project-101-firebase-adminsdk-cb748-fhry6shja.json"

Test that it's done correctly using - set GOOGLE_APPLICATION_CREDENTIALS


Finally to test run the cloud functions on emulator, I followed this nicely written article:
https://medium.com/@moki298/test-your-firebase-cloud-functions-locally-using-cloud-functions-shell-32c821f8a5ce

Basically -

  1. Open CMD in administrator mode, and navigate to your functions folder.
  2. Run transpile command for your function ts file. This will be required everytime we make a change in our code.

npm run-script build

  1. Enter firebase functions shell with command:

firebase functions:shell

  1. Run your function and see that it works well (hopefully!). Say the function is http cloud function with name TestFunc - so in functions shell type:

TestFunc()

That should do it.

Go to link https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk above. Generate a private key there. Save it to a folder on your pc. Say "D:\Path\project-101-firebase-adminsdk-cb748-fhry6shja.json". Then on the index.ts file of your functions folder, update the code as follows:

`
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

var serviceAccount = require("D://Path//project-101-firebase-adminsdk-cb748-fhry6shja.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://project-101.firebaseio.com"
});
`

@pranaykothari You rock 🤘🏻 !

For anyone who see this, just place the downloaded json in your repo's /functions directory, and import it like
const credential = require("./credentails.json").
You can rename the json to something like "credentails.json" so it will be easier to understand your files.

⚠️ WARNING: You should not commit this type of file. It's very sensitive. Exclude it from commits by adding its name in your functions/.gitignore.

I done

gcloud auth application-default login
Your browser has been opened to visit:

and it worked but get

users.js:60 Error listing users: 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 configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. 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 configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. 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"}}"

I also tried this:

Download the admin file and export like so in bash:
export GOOGLE_APPLICATION_CREDENTIALS="$HOME/svelte-fullstack-starter-firebase-adminsdk-4bq35-xxxx.json"

but when running the emulator I get the same issue as above
image

@quantuminformation when you do gcloud auth application-default login you're getting user credentials (firebase logini is the same kind of credential). Some APIs, like the identitytoolkit API which powers Firebase Auth, do not accept those credentials.

If you want to use those APIs you should use a service account to authenticate. Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to point to a service account private key JSON file:
https://cloud.google.com/docs/authentication/getting-started#setting_the_environment_variable


Edit I see you've already done this. If you're using the env var and the emulator is not respecting your credentials, you should file a new issue.

I upgraded to
8.4.3 and it worked fine

Mac OS

[REQUIRED] Test case

Functions code: https://github.com/quantuminformation/svelte-firebase-starter/tree/master/functions

[REQUIRED] Steps to reproduce

  • Run gcloud auth application-default login in the above dir

Creates file Credentials saved to file: [/Users/nikos/.config/gcloud/application_default_credentials.json]
nice new touch)

  • I then remove my existing one
    The environment variable [GOOGLE_APPLICATION_CREDENTIALS] is set to:
    [/Users/nikos/svelte-fullstack-starter-firebase-adminsdk-4bq35-f77b2
    b4fc4.json]

and this is created:
image

  • Finally I run firebase emulators:start --only functions --inspect-functions

image

When I run my app pointing to local emulation
base = "http://localhost:5002/svelte-fullstack-starter/us-central1"

debugging works fine using my live data!

For my case, sync the time on local pc/laptop with time server fixed the problem, Thanks! @pranaykothari

Hey everyone. Version 8.5.0 of the CLI includes this change:
https://github.com/firebase/firebase-tools/pull/2214

With that change you should no longer need to run gcloud auth application-default login to use the emulators (although you can if you want to). As long as you are logged in with firebase login we will pass your user credential into the Functions emulator.

So I believe this issue should now be fixed. If you have further unexpected auth behavior please file a new issue and mention me!

Do you need generate SDK admin firebase in your project.

Acess "Settings" > "services account" and generate SDK admin firebase

Was this page helpful?
0 / 5 - 0 ratings