How to access admin firestore using firebase admin SDK? - node.js

I am working on an application, where it uses Next.js and Firebase.
I need to implement server-side authentication. Firebase allows connecting the server using Firebase Admin SDK.
const admin = require("firebase-admin");
const serviceAccount = require("../../../../3-firebase/service-account-key/service-account-file.json");
try {
admin.initializeApp({
credential: admin.credential.cert({
client_email: process.env.FIREBASE_CLIENT_EMAIL,
private_key: process.env.FIREBASE_PRIVATE_KEY,
project_id: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
}),
});
console.log("Initialized.");
} catch (error) {
if (!/already exists/u.test(error.message)) {
console.error("Firebase admin initialization error", error.stack);
}
}
const db = admin.firestore();
export { db };
I installed the firebase-admin package using NPM and I setup firebase admin SDK using the above code by creating a separate file called "firebase-admin.js"
import { initializeApp } from "firebase/app";
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
};
const defaultApp = initializeApp(firebaseConfig);
export default defaultApp;
The above code is the default firebase application setup in a separate file called "firebase.js"
The problem I encountered is I am not able to access the admin firestore. However, I can able to access the default firestore.
What I observed is admin SDK is able to initialize using the credentials (private key). But I don't know why I can't access admin firestore. I mean when i use admin firestore the console gives error of 500 (internal server error)
Here is the error message, when I try to use admin.firestore()
{"error":{"code":"invalid-argument","name":"FirebaseError"}}
versions I am using
"firebase": "^9.6.6",
"firebase-admin": "^10.0.2",
Timely help is much needed

You're importing the initializeApp method from the Firebase Javascript SDK. You should be importing from the Firebase Admin SDK.
import { initializeApp } from "firebase/app";
vs.
import { initializeApp } from "firebase-admin/app";

Using firebase-admin v10.0.2 I was able to successfully access the db adding this in my config.js file, similar to your firebase.js file.
const ServiceAccount = require('../superSecretServiceKeyFile.json');
const app = initializeApp(ServiceAccount);
const { getFirestore } = require('firebase-admin/firestore');
const db = getFirestore(app);

Related

How to use Firebase Cloud Functions with the new modular Firestore API?

I have upgraded my Firebase v8 project to v9. The web application now uses the modular SDK with the new functional API for Firestore.
In this project I use Firebase Functions. There I have upgraded to firebase-admin 11.0.0. But it seams it does not provide the new functional API for Firestore.
const { initializeApp } = require('firebase-admin/app');
const app = initializeApp();
import { getFirestore } from "firebase/firestore";
const db = getFirestore(app);
This throws:
TypeError: Cannot read properties of undefined (reading 'getProvider')
at Object._getProvider (/p/happygast/node_modules/#firebase/app/src/internal.ts:110:6)
at Object.getFirestore (/p/happygast/node_modules/#firebase/firestore/src/api/database.ts:185:10)
Now I am not sure if I am doing something wrong? Or is there no functional Firestore API for Cloud Functions?
In essence: Is firebase-admin/app compatible with firebase/firestore? Or: How do I initialize and use firebase/firestore in Firebase Cloud Functions?
You are importing initializeApp() from the Firebase Admin SDK but getFirestore() from the Firebase Client SDK and then passing an instance of Admin SDK in it that's invalid. Instead, you should import Firestore from the Admin SDK itself as shown below:
const { initializeApp } = require('firebase-admin/app');
const { getFirestore } = require('firebase-admin/firestore'); // not firebase/firestore
// Initialize by ADC or another service account
const app = initializeApp();
const db = getFirestore(app);
If you want to use the client SDK, then you'll have to initialise the Firebase instance using the client SDK itself:
const { initializeApp } = require('firebase/app');
const { getFirestore } = require('firebase/firestore');
// use the web config that can be found in Firebase console
const clientApp = initializeApp({ ...config });
cpmst db = getFirestore(clientApp);

how to initialize firebase admin SDK in nodejs

I am try to initialize firebase admin SDK in my project but it is not working. I intend using it in my next js API for admin backend
import {
initializeApp,
applicationDefault,
cert,
} from "firebase-admin/app";
import {
getFirestore,
Timestamp,
FieldValue,
} from "firebase-admin/firestore";
import serviceAccount from "../secret.json";
const app = initializeApp({
credential: cert(serviceAccount),
});
export default app.getFirestore();

Firebase database isn't starting

I am a newbie in JavaScript. Recently I have installed firebase admin and kept the code in global scope, database.js. Like this.
import app from 'firebase-admin';
import firebase_key from './firebase_key.js';
app.initializeApp({
credential: app.credential.cert(firebase_key),
databaseURL: "https://study-boss-681fa-default-rtdb.firebaseio.com"
});
console.log('database started');
export default app.database();
Now I want to access this database from my service class. My serice class is
import { getDatabase} from "firebase-admin/database";
const database = getDatabase();
This service class code is throwing the following error.
FirebaseAppError: The default Firebase app does not exist. Make sure you call initializeApp() before using any of the Firebase services.
If you are just using getDatabase() directly then there's a high chance that it's being access before your initializeApp is executed. I would recommend initializing all Firebase services in a single file and importing them wherever required as shown below:
import { initializeApp } from 'firebase-admin/app';
import { getDatabase } from 'firebase-admin/database';
import firebase_key from './firebase_key.js';
const app = initializeApp({
credential: app.credential.cert(firebase_key),
databaseURL: "https://study-boss-681fa-default-rtdb.firebaseio.com"
});
const database = getDatabase(app);
console.log('database started');
export { database };
Now you can import { database } from "..path/to/firebase.js" wherever required.

How to manage tenants programatically in Google Cloud Platform

I am writing a backend service to manage my tenants in gcp. Specifically, I’d like to be able to create/delete and list tenants, on my node server.
The Firebase admin-sdk should enable me to do so. When I try to run it I get this 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".
I followed this documentation to set up install the admin sdk. (tried windows and linux, using an environment variable)
I used this documentation (Getting an existing tenant)
This is my code:
var admin = require('firebase-admin');
var app = admin.initializeApp({
credential: admin.credential.applicationDefault(),
projectId: 'myProject'
});
admin.auth().tenantManager().getTenant("myTenant")
.then((tenant) => {
console.log(tenant.toJSON());
})
.catch((error) => {
// Handle error.
console.log(error.message)
});
const someOtherStuff = () =>...
module.exports = {
someOtherStuff
}
Edit: I am running this code locally on a node server with Express. I am using a Windows computer and a Linux computer. The result is the same on both systems.
I was able to work around the problem by changing the initialization. Instead of using environment variables, I used the service account key file directly, as described here
Some sample code of how I use it:
var admin = require('firebase-admin');
var {getAuth} = require('firebase-admin/auth');
var serviceAccount = require('/path/to/serviceAccountKey.json');
// Initialize the default app using seriveAccount instead of environment variables
var app = admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
const createTenant = async (tenantName) => getAuth(app).tenantManager().createTenant({
displayName: tenantName,
emailSignInConfig: {
enabled: true,
passwordRequired: true, // Email link sign-in enabled.
}
}).then((createdTenant) => {
return createdTenant.toJSON();
}).catch((error) => {
console.log("tenant could not be created. " + error.message);
});
//some other stuff...
module.exports = {
createTenant,
someOtherStuff,
}

DB.collection is not a function in firebase?

I am trying to connect to firebase realtime database (not firestore) but I get the error that db.collection is not a function. Other answers in StackOverflow are mentioned with respect to Firestore. Thanks for your help.
const admin = require('firebase-admin');
// Firebase configuration - this should not be public.
// Please use your own config if you intend to use this code.
var firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxx",
authDomain: "xxxxxxxxxxxxxxxxxx",
databaseURL: "xxxxxxxxxxxxxxxxxx",
projectId: "xxxxxxxxxxxxxxxxxx",
storageBucket: "xxxxxxxxxxxxxxxxxx",
messagingSenderId: "xxxxxxxxxxxxxxxxxx",
}
// Initialize Firebase
admin.initializeApp(firebaseConfig)
const db = admin.database();
console.log("Database setup");
(async () => {
try {
let query = db.collection('users');
console.log("Doing database query now");
await query.get().then(querySnapshot => {
console.log(querySnapshot);
});
} catch (error) {
console.log(error);
}
})();
const db = admin.database() is an instance of Firebase realtime database and not Firestore. To get an instance of Firestore, use admin.firestore().
const admin = require('firebase-admin');
admin.initializeApp(/* service account */)
const db = admin.firestore();
console.log("Firestore setup");
Admin SDK uses a service account and not the same public credentials. You can refer to the documentation for detailed information. You can get a service account from project settings.
Do note that if you are using Cloud functions then you can leave initializeApp() empty.

Resources