After coding some of my firebase functions, I deployed and got the following error:
Unexpected error while acquiring application default credentials: Could not load the default credentials.
I researched this error and came to the conclusion that this post would solve my issue: Firebase Cloud Functions: Error: Unexpected error while acquiring application default credentials: read ECONNRESET
I tried this solution. I downloaded a new private key to my desktop and then inserted the following code:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
var serviceAccount = require('/Users/nikhilsridhar/Desktop/test-eed0a-firebase-adminsdk-c4tmt-5d905a082b.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://test-eed0a.firebaseio.com"
});
However this does not solve my problem, but rather gives me a new error:
Error: Cannot find module '/Users/nikhilsridhar/Desktop/test-eed0a-firebase-adminsdk-c4tmt-5d905a082b.json'
What am I doing wrong?
So after some time I figured out that the service account file must be within the functions folder. Then make the path relative or in my example: ./test-eed0a-firebase-adminsdk-c4tmt-5d905a082b.json. This should work.
The function admin.credential.cert() receives a string parameter with the path of the firebase json key, this code works well for me with the auth method, you should add databaseURL and call .firestore() instead of auth():
import admin from 'firebase-admin'
export default admin.initializeApp({
credential: admin.credential.cert('../../firebase-key.json')
}).auth()
Watch what TypeScript says about that method:
cert(serviceAccountPathOrObject: string | admin.ServiceAccount, httpAgent?: Agent | undefined): Credential
Optional | HTTP Agentto be used when retrieving access tokens from Google token servers.
The path to a service account key JSON file or an object representing a service account key.
See | Initialize the SDK for more details.
#example
// Providing a path to a service account key JSON file
const serviceAccount = require("path/to/serviceAccountKey.json");
initializeApp({
credential: cert(serviceAccount),
databaseURL: "https://<DATABASE_NAME>.firebaseio.com"
});
#example
// Providing a service account object inline
initializeApp({
credential: cert({
projectId: "<PROJECT_ID>",
clientEmail: "foo#<PROJECT_ID>.iam.gserviceaccount.com",
privateKey: "-----BEGIN PRIVATE KEY-----<KEY>-----END PRIVATE KEY-----\n"
}),
databaseURL: "https://<DATABASE_NAME>.firebaseio.com"
});
#returns
A credential authenticated via the provided service account that can be used to initialize an app.
Related
Summary of Problem
I'm hosting my Node.js server that uses Firebase on Heroku and when I try to run on Heroku, I get the error below that it can't load my credentials.
It works perfectly when running on my local machine. I'm using the firebase-admin npm package to configure my firebase connection/instance.
Has anyone encountered this before? If so, I'd love your help!
Error from Heroku
Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
Code
Firebase Admin Config File
This is the file I'm using to configure my Firebase admin instance
const admin = require('firebase-admin');
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: "https://esports-competition-2.firebaseio.com"
}); //this also allows me to use Google OAuth2 refresh token
const db = admin.firestore();
module.exports = db;
Function to save data to firebase
const db = require("../../configs/firebaseConfig");
async function firestorePush(userId, eventType, data) {
try {
//read database
//if userId contains eventType singleEntry then remove from database
const timeStamp = new Date();
userId = userId.toString();
const userDoc = db.collection("pushData").doc(userId);
const pushData = await userDoc.set(
{
event: {
eventType,
data,
timeStamp
}
},
{ merge: true }
);
console.log("Document set in FireStore", pushData);
} catch (err) {
console.log("errpr pushing to firebase", err);
}
}
According to the documentation on admin.credential.applicationDefault():
Google Application Default Credentials are available on any Google infrastructure, such as Google App Engine and Google Compute Engine.
Since Heroku is not Google infrastructure, you will have to initialize the Admin SDK with one of the other options shown in the documentation on initializing the SDK.
I'm using Firebase 7.0.0. When using firebase functions:shell, I receive the following error whenever I try to get() a document or listDocuments() in a collection, with no further info: "Error: Getting metadata from plugin failed with error: invalid_grant". Note that all works fine when the same code is deployed to Firebase Cloud Functions.
import * as functions from 'firebase-functions'
import * as firebase from 'firebase-admin'
try { firebase.initializeApp() } catch ( error ) { }
exports = module.exports = functions.https.onRequest(
async ( request: functions.https.Request, response: functions.Response ) => {
if ( request.method === 'POST' ) {
await firebase.firestore().collection( `users` )
.listDocuments()
.then( ( documents: FirebaseFirestore.DocumentReference[] ) => {
for ( const document of documents ) {
console.log( `Found ${document.id}`)
}
response.status( 200 ).end()
}
)
.catch( ( error: any ) => {
console.error( `List failed: ${error}` )
response.status( 405 ).end()
}
)
}
else {
console.error( `Unexpected ${request.method}` )
}
}
)
What am I doing doing incorrectly?
I got the same error. "Error: 400 undefined: Getting metadata from plugin failed with error: invalid_grant".
in my case, the problem was from firebase.initializeApp()
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: 'https://<DATABASE_NAME>.firebaseio.com'
});
There wasn't any problem when I was doing only one project, but it started to happen when I tried testing 2 firebase function projects.
admin.credential.applicationDefault() setting is only for one project configuration, so only one project will work and others won't work if you have more then 2 firebase fuctions projects with that setting.
So, to solve this problem
In the Firebase console, open Settings > Service Accounts.
Click Generate New Private Key, then confirm by clicking Generate Key.
Securely store the JSON file containing the key.
When authorizing via a service account, you have two choices for providing the credentials to your application. You can either set the GOOGLE_APPLICATION_CREDENTIALS environment variable, or you can explicitly pass the path to the service account key in code. The first option is more secure and is strongly recommended.
To set the environment variable:
Set the environment variable GOOGLE_APPLICATION_CREDENTIALS to the file path of the JSON file that contains your service account key. This variable only applies to your current shell session, so if you open a new session, set the variable again.
Linux or macOS
export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"
windows with PowerShell:
$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"
if you want to pass the path to the service account key in code.
var admin = require("firebase-admin");
var serviceAccount = require("path/to/serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://<DATABASE_NAME>.firebaseio.com'
});
https://firebase.google.com/docs/admin/setup?authuser=0 is an official document link about Adding the Firebase Admin SDK to the server.
I hope it will help someone.
I'm trying to create a firebase cloud function. So I would to run my firebase cloud function locally.
But it do not work how to setup authentication.
I have installed firebase tools : https://firebase.google.com/docs/functions/local-emulator
I've runned the command firebase login, so now I'm logged.
Then I've created my json key with this tutorial : https://cloud.google.com/docs/authentication/getting-started
Now if I type echo $GOOGLE_APPLICATION_CREDENTIALS the result is /home/$USER/.google/****.json which contain
"project_id","private_key_id","private_key","client_email", "client_id", "auth_uri", "token_uri", "auth_provider_x509_cert_url", "client_x509_cert_url"
Also I've tried to install the full google cloud sdk and I runned : gcloud auth application-default login but no success.
Npm package versions :
"firebase-functions":"3.0.2"
"firebase-admin": "8.2.0"
I think I've provided enought information but feel free to ask me more if you want.
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const express = require("express");
const app = express();
app.get("/", async (req, res) => {
admin.firestore().collection('something').get().then((collection) =>
return res.send({"count": collection.docs.length, "status": 200});
});
exports.exports = functions.https.onRequest(app);
the code is not important, the most important thing is that even I've done all theses steps, when I emulate my firebase locally with firebase serve and I trigger a function, I have this error :
Error: The incoming JSON object does not contain a client_email field
I can ensure you the json file contains client_email field.
Can you help me to authenticate with google ?
Thanks for your help.
I had a similar problem. It's likely a bug in version 7.0.2 of firebase-tools. I rolled back to version 7.0.0 and it works now.
So the temporary solution is:
npm i firebase-tools#7.0.0 -g
In short:
admin.initializeApp({ credential: admin.credential.applicationDefault() });
See docs for admin.credential.applicationDefault()
Update: Note that this is only recommended for testing/experimenting:
This strategy is useful when testing and experimenting, but can make
it hard to tell which credentials your application is using. We
recommend explicitly specifying which credentials the application
should use, ... Source
A little more info
I had the same when trying to call a firebase function locally which tries to update some documents in firestore database in batch. (Didn't test without batch).
To start calling firebase functions locally, I use:
firebase function:shell
As you probably know, this lists the available functions for your project.
I called my function and got the following error callstack:
Unhandled error Error: The incoming JSON object does not contain a client_email field
> at JWT.fromJSON (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\google-auth-library\build\src\auth\jwtclient.js:165:19)
> at GoogleAuth.fromJSON (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\google-auth-library\build\src\auth\googleauth.js:294:16)
> at GoogleAuth.getClient (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\google-auth-library\build\src\auth\googleauth.js:476:52)
> at GrpcClient._getCredentials (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\google-gax\build\src\grpc.js:107:40)
> at GrpcClient.createStub (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\google-gax\build\src\grpc.js:223:34)
> at new FirestoreClient (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\#google-cloud\firestore\build\src\v1\firestore_client.js:128:39)
> at ClientPool.Firestore._clientPool.pool_1.ClientPool [as clientFactory] (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\#google-cloud\firestore\build\src\index.js:315:26)
> at ClientPool.acquire (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\#google-cloud\firestore\build\src\pool.js:61:35)
> at ClientPool.run (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\#google-cloud\firestore\build\src\pool.js:114:29)
> at Firestore.readStream (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\#google-cloud\firestore\build\src\index.js:995:26)
RESPONSE RECEIVED FROM FUNCTION: 500, {
"error": {
"status": "INTERNAL",
"message": "INTERNAL"
}
}
I was running my function locally using the command line:
firebase functions:shell
I was using this code:
// Reference report in Firestore
const db = admin.firestore();
admin.initializeApp();
export const performMyCallableFirebaseFunction = (db, { from, to }) => {
return db.collection("collectionName").where("prop", "==", from).limit(500).get().then(snapshot => {
if (snapshot.empty) return new Promise(resolve => resolve(`No docs found with prop: ${from}`));
const batch = db.batch();
snapshot.forEach(doc => batch.update(doc.ref, { prop: to }));
return batch.commit();
});
};
exports.myCallableFirebaseFunction = functions.https.onCall(data => performMyCallableFirebaseFunction(db, data.from, data.to));
I changed the line
admin.initializeApp();
to
admin.initializeApp({ credential: admin.credential.applicationDefault() });
and now I was able to call my function locally using:
firebase functions:shell
firebase > myCallableFirebaseFunction({from: "foo", to: "bar"})
See docs for admin.credential.applicationDefault()
You probably need to set up the Firebase Admin SDK to use the Firebase emulator. You can do it by passing a credential property when calling the admin.initializeApp() method:
const serviceAccount = require('../serviceAccount.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
You can download your service account JSON file in the Firebase console:
Click on the "settings" icon;
Go to "Users and permissions";
Click on the link where it says "N service accounts also have access to this project";
Click on the "Generate new private key" button.
Here is how I've solved the problem after struggling couple of hours:
Short answer:
Create Firebase-adminsdk key
How to do it:
Go to Google-cloud-platform > Service accounts https://console.cloud.google.com/iam-admin/serviceaccounts/
Select your project
Select your firebase-admin-sdk looks like firebase-adminsdk-u4k3i#example..
Enable edit mode
Create key and select JSON
You get the option to download a .json. Which has ProjectID, PrivateKey and ClientEmail in it
use the information like this where you initialize your app:
// Providing a service account object inline
admin.initializeApp({
credential: admin.credential.cert({
projectId: "<PROJECT_ID>",
clientEmail: "foo#<PROJECT_ID>.iam.gserviceaccount.com",
privateKey: "-----BEGIN PRIVATE KEY-----<KEY>-----END PRIVATE KEY-----\n"
})
});
Once you have created a Firebase project, you can initialize the SDK with an authorization strategy that combines your service account file together with Google Application Default Credentials.
To authenticate a service account and authorize it to access Firebase services, you must generate a private key file in JSON format.
To generate a private key file for your service account:
In the Firebase console, open Settings > Service Accounts.
Click Generate New Private Key, then confirm by clicking Generate Key.
Securely store the JSON file containing the key.
Set the environment variable GOOGLE_APPLICATION_CREDENTIALS to the file path of the JSON file that contains your service account key. This variable only applies to your current shell session, so if you open a new session, set the variable again.
$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"
https://firebase.google.com/docs/admin/setup?authuser=3
I was getting this error when running firebase emulators:start.
As per the investigation from this bug: https://github.com/firebase/firebase-tools/issues/1451, it seems that this is an issue with referencing the app directly instead of via the admin module.
i.e. this causes the error:
const app = admin.initializeApp();
const firestore = app.firestore();
but this does not:
admin.initializeApp();
const firestore = admin.firestore();
However for the original question, you're using admin.firestore() so that wouldn't be the problem. It seems that admin.initializeApp() is never called. Perhaps that could be the cause of your issue?
I'm getting this error in my terminal:
#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: \"Failed to parse
access token response: Error: Error while making request: getaddrinfo
ENOTFOUND metadata.google.internal metadata.google.internal:80. Error
code: ENOTFOUND\"."}`
when using firebase-tools. This is the simple node script I'm trying to run.
const admin = require("firebase-admin");
const firebase = admin.initializeApp({
apiKey: "MY_API_KEY",
authDomain: "APP_ID.firebaseapp.com",
databaseURL: `https://DATABASE_URL.firebaseio.com`,
projectId: "APP_ID"
});
const snap = firebase
.database()
.ref("REF")
.child("ID")
.once("value");
console.log(snap);
Firebase tools version: 5.0.1
I've tried uninstalling and reinstalling, logging in and out of firebase-tools with firebase login / firebase-logout
the configuration has the wrong structure and lacks fields ...
admin.initializeApp({
databaseURL: 'https://<DATABASE_NAME>.firebaseio.com',
credential: admin.credential.cert({
projectId: '<PROJECT_ID>',
clientEmail: 'foo#<PROJECT_ID>.iam.gserviceaccount.com',
privateKey: '-----BEGIN PRIVATE KEY-----\n<KEY>\n-----END PRIVATE KEY-----\n'
})
});
you cannot just use the "web" configuration to access the Firebase Admin SDK.
because if this would be possible, the private key would be exposed to the public.
see the documentation.
I solved it simply by running :
firebase login
I also have this error when I don't have an internet connection.
i created a web app using node js express and firebase. i created a form which will upload a file to firebase but when i tried what's on the guide it gives an error..
var firebase = require('firebase');
var config = {
apiKey: "----------------------------------",
authDomain: "----------------------------------",
databaseURL: "-",----------------------------------
projectId: "---------",
storageBucket: "----------------",
messagingSenderId: "---------------"
};
firebase.initializeApp(config);
module.exports = firebase;
// Get a reference to the storage service, which is used to create references in your storage bucket
var storage = firebase.storage();
// Create a storage reference from our storage service
var storageRef = storage.ref();
this is the set up i use for using firebase on node js.
var storage = firebase.storage();
^
TypeError: firebase.storage is not a function
and this is the error i receive from the console. after searching they said that i need to use google-cloud npm. so my question is if i install google-cloud on my node do i need to create an account on google cloud platform?..
Node js google-cloud package is used instead of firebase to store files, videos etc. Right now firebase storage is not compatible with Nodejs that's why you are getting that error^, yoou can do something like this to use google-cloud:-
npm install --save google-cloud
And then to use storage in your project this is a sample code:-
const gcloud = require('google-cloud');
const storage = gcloud.storage({
projectId: //project id here,
keyFilename: //service account credentials here,
});
const storagebucket = storage.bucket('projectID.appspot.com');
This link here has the complete guide how to do google-cloud stuff.
https://medium.com/#stardusteric/nodejs-with-firebase-storage-c6ddcf131ceb