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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With