Using firebase-admin. What are service account credentials used for? - node.js

I'm building a cloud function to get some documents and generate an HTML response.
And right now what I have is:
myFunction.js
import * as admin from 'firebase-admin';
import serviceAccount from './someServiceAccountKey.json';
// OPTION #1 <-----
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://myfirebaseproject.firebaseio.com"
});
// OPTION #2 <------
admin.initializeApp();
// FUNCTION <------
async function(req,res) {
const docSnapshot = await admin.firestore().collection('someCollection').doc('someDoc').get();
// AND SO ON...
}
At some point I've created that serviceAccount key (I don't remember from which tutorial) and I've been using on my functions to "grant access" to the firebase-admin (as in OPTION #1 from the code above). Because I thought I needed to.
But I've found out that even without any initializing parameter or serviceAccount credential (as in OPTION #2 from the code above), I can initialize the firebase-admin and access my firebase project resources (like Firestore) without any issues.
And I can do this on deployed functions, which makes sense, since they are inside the Firebase project's cloud environment, and if they were deployed, they should have access to the project's resources, without the need for a service account, right?
But I also found out that I can do this in my Node.js local environment. By calling the function with npx babel-node myFunction.js (using babel node to transpile and execute). The function is able to access and query my Firestore (on-line data, this is not the Firestore emulator) without any issues.
Where is my local environment getting permission to access my project's resources from? Is it from the firebase-tools that is installed and logged in my project?
If I don't need them in both cases. What are service accounts mainly used for?

You initialize SDK in different way depending on the environment:
Cloud Functions
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
let db = admin.firestore();
Google Cloud Platform
const admin = require('firebase-admin');
admin.initializeApp({
credential: admin.credential.applicationDefault()
});
const db = admin.firestore();
// ...
Node server
const admin = require('firebase-admin');
let serviceAccount = require('path/to/serviceAccountKey.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
let db = admin.firestore();
Look here for more details
So, your observations are correct.
However, since even using OPTION #2 you are getting access to your firebase, then most likely you need to check your database rules and make sure you are prohibiting unauthenticated access to your db.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid != null;
}
}
}
More about the rules here.

Firebase data is secured using rules, before you set up any rules, any user (even unauthenticated) can access your data.
https://firebase.google.com/docs/rules/basics
Once you have rules set up, then either the user or the server will have to authenticate in order to read/write data.
Users authenticate by logging on with google (or whatever client side security you have ocnfigured).
Servers authenticate by using the service account. Service accounts default to having admin access to the database.
https://firebase.google.com/docs/database/admin/start#authenticate-with-admin-privileges

Related

Firebase Functions Service Accounts with Two Projects

I have two firebase projects, one for production and one for development. I've created service account keys for both projects and I initialize admin in my functions folder like so:
const admin = require("firebase-admin");
const serviceAccount = require("./service-account.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
storageBucket: "some-app.appspot.com",
});
const db = admin.firestore();
module.exports = {
db,
admin,
};
But I need firebase to use the appropriate service account for each project. My app is setup to use the production project when deployed in production, but the way I've set up admin.js (above) it always takes the development service-account credentials.
How can I set the service account credentials as an environment variable? Is there a way to add the key to firebase config in the console? Or should I just hard code in the production service account and live with that?
I found this in the docs, but it doesn't appear to solve my problem.
serviceAccount = require('./serviceAccount.json');
const adminConfig = JSON.parse(process.env.FIREBASE_CONFIG);
adminConfig.credential = admin.credential.cert(serviceAccount);
admin.initializeApp(adminConfig);
I appreciate any help you can provide.
You could specify the configuration to use in an environment variable as shown here and then pick that up in your code.
But that should not be necessary in most cases, since calling admin.initializeApp() without parameters already initializes the Admin SDK with the administrative credentials for the current project.

How to use firebase oauth as a login tool for vps applications.?

Hello all firebase experts,
I just learned about node.js today, and I intend to use firebase oauth as a login tool in my application and install the application on vps, is there a suggestion that the NPM package should be used? or is there a simple example that I can understand?
At server side (Node) you won't need to OAuth but you may need to OAuth as Admin. And for this;
var admin = require("firebase-admin");
// Fetch the service account key JSON file contents
var serviceAccount = require("path/to/serviceAccountKey.json");
// Initialize the app with a service account, granting admin privileges
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://databaseName.firebaseio.com"
});
// As an admin, the app has access to read and write all data, regardless of Security Rules
var db = admin.database();
var ref = db.ref("restricted_access/secret_document");
ref.once("value", function(snapshot) {
console.log(snapshot.val());
});

Firebase: How to verify Google login token id from Android & iOS

I want to verify on my node backend all the tokens (Google login) i get from my Android app. I started with initializing the firebase module like this:
var admin = require('firebase-admin');
var serviceAccount = require('googlefirebase');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: url
});
This gave me some error about some DEFAULT name and i found out that i needed to use this code:
var admin = require('firebase-admin');
var serviceAccount = require('googlefirebase');
admin.initializeApp(functions.config().firebase);
Then i realize that i need to install and init the project on my server so i did this:
firebase login
firebase init
firebase use --add project
firebase functions:config:set "google-services.json" (just the project_info data of the json that i downloaded from firebase)
Now i get this error:
Error: Must initialize app with a cert credential or set your Firebase
project ID as the GOOGLE_CLOUD_PROJECT environment variable to call
verifyIdToken()
EDIT START
I get this error when i call:
admin.auth().verifyIdToken(token).then(function(decodedToken) {}.catch(){};
EDIT END
I already "init" firebase (or at least i thing so) and created the environment variables: GOOGLE_CLOUD_PROJECT and FIREBASE_CONFIG and i keep getting the same error.
So, whats the right way to get firebase to work? what am i missing? is verifyIdToken the right method to verify the token? i just want to verify the google login token.
With Cloud Functions for Firebase, you're not supposed to initialize like this any more:
admin.initializeApp(functions.config().firebase);
You're supposed to use no arguments:
admin.initializeApp();
Also, your google-services.json file is not useful in Cloud Functions. That's only for use in an Android app.
you should have a FIREBASE_CONFIG environments variable and then call
// Initialize the default app
var admin = require('firebase-admin');
var app = admin.initializeApp();
that config variable contain the initialize information like :
databaseURL: 'https://databaseName.firebaseio.com',
storageBucket: 'projectId.appspot.com',
projectId: 'projectId'

configuring firebase realtime database

Already i have initialized firebase with firebase functions and deployed. I am using fulfillment and i am not using separate server. i am using firebase only, ie. I have developed javascript code and deployed in firebase itself.
Now I want to configure firebase realtime database with this project.
Can I use below sample code?
var admin = require("firebase-admin");
// Fetch the service account key JSON file contents
var serviceAccount = require("path/to/serviceAccountKey.json");
// Initialize the app with a service account, granting admin privileges
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://databaseName.firebaseio.com"
});
// As an admin, the app has access to read and write all data, regardless of Security Rules
var db = admin.database();
var ref = db.ref("restricted_access/secret_document");
ref.once("value", function(snapshot) {
console.log(snapshot.val());
});
I have few questions:
where to start configuring firebase realtime database?
How to get file "serviceAccountKey.json"? since,i am not using separate server.
How to get database URL?
Did OAuth configuration is required before database?
I believe since V1 you don't need to configure the admin since it takes the config form the server by itself checkout this link for more info https://firebase.google.com/docs/functions/beta-v1-diff#new_initialization_syntax_for_firebase_admin

FIREBASE WARNING: Provided authentication credentials are invalid

I am trying to use Firebase in node.js but every time I restart the server I am getting following error:
FIREBASE WARNING: Provided authentication credentials are invalid. This usually indicates your FirebaseApp instance was not initialized correctly. Make sure your apiKey and databaseURL match the values provided for your app at https://console.firebase.google.com/, or if you're using a service account, make sure it's authorized to access the specified databaseURL and is from the correct project.
Following is my index.js:_
var express = require('express');
var router = express.Router();
var mongoose=require('mongoose');
var admin=mongoose.model('admin');
var firebase = require("firebase");
// Initialize the app with no authentication
firebase.initializeApp({
serviceAccount: {
projectId: "...",
clientEmail: "...",
privateKey: "-----BEGIN PRIVATE KEY-----...",
},
databaseURL: "..."
});
console.log("sfsaf")
// The app only has access to public data as defined in the Security Rules
var db = firebase.database();
var ref = db.ref("unitalk-b9145");
var messagesRef = ref.child("messages");
messagesRef.push({
name:"Rupali",
post:"Demo test of firebase"
});
Although I have checked the path of service-account and databaseURl..
Please help..
You can not log in with the service account using the "firabase" package. You need to use the "firabase-admin" package for this. You can find detailed information here (https://firebase.google.com/docs/database/admin/start).
UPDATED: 8 Nov 2016
go to : https://console.firebase.google.com
To use the Firebase Admin SDKs, you'll need a Firebase project, a service account to communicate with the Firebase service, and a configuration file with your service account's credentials.
Navigate to the Service Accounts tab in your project's settings
page.
Select your Firebase project. If you don't already have one, click
the Create New Project button. If you already have an existing
Google project associated with your app, click Import Google Project
instead.
Click the Generate New Private Key button at the bottom of the
Firebase Admin SDK section of the Service Accounts tab.
After you click the button, a JSON file containing your service
account's credentials will be downloaded. You'll need this to
initialize the SDK in the next step.
Sample 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"
});
Another method to solve the issue link
for those who still facing this issue, you may try on this method, this is related to the project roles management according to the description inside
For anyone looking at this recently. I had the problem with Firebase function, after changing project. It went away when i removed the keys from admin.initializeApp()
Apparently firebase functions now know to use the project credentials. So just this;
admin.initializeApp();
You are using require('firebase') module so u need the following things:
var config = {
apiKey: " [your api key]",
authDomain: "[projectname].firebaseapp.com",
databaseURL: "https://[projectname].firebaseio.com/",
storageBucket: "[projectname].appspot.com",
messagingSenderId: "[message id]",
};
firebase.initializeApp(config);
If you want to use require("firebase-admin") then you have to configure
serviceAccountKey.json(downloaded file) file ...
I am able to connect with firebase successfully.

Resources