React Native with Expo: is firebase-admin necessary? - firebase

I need to fetch my firebase db before the authentication process.
My firebase rules are restricted to authenticated users for both read and write.
So I've installed firebase-admin.
in the App.js
import * as admin from 'firebase-admin';
and after initialised it
const serviceAccount = require("./pathtocredentials.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://myappdbname.firebaseio.com"
});
This is the error that I have:
The package at "node_modules\firebase-admin\lib\firebase-namespace.js"
attempted to import the Node standard library module "fs". It failed
because React Native does not include the Node standard library. Read
more at
https://docs.expo.io/versions/latest/introduction/faq/#can-i-use-nodejs-packages-with-expo
Failed building JavaScript bundle.
So I searched and ..."Since your app is running inside JS VM on either iPhone or Android, the only way to access filesystem is to use react-native-fs"
What I want is just to check in my db if a user exists before let it authenticate. Did I necesserily need firebase-admin and react-native-fs ?

firebase-admin is not meant for web frontend code. It's for backend code running nodejs. You won't be able to effectively use firebase-admin in a React or any browser environment. On top of that, it's not really necessary if you just want to query your database from your frontend.
All you really need to do is read data using the normal Firebase JavaScript API for web. You can tell if a node exists in the database by checking if its DataSnapshot object actually exists.

Related

GOOGLE_APPLICATION_CREDENTIALS for dummy Firebase project

I'm learning to set up Firebase Emulators correctly to work on my projects and I came up with a problem. I can setup the emulators and make them work locally, however, when trying to access firestore it seems to try to access the real Firestore Instance instead of the emulator.
Right now I'm initializing the app like this (in Cloud Functions)
admin.initializeApp();
const db = admin.firestore();
But when I'm running a function I'm getting:
Failed to initialize and load triggers. This shouldn't happen: Failed to read credentials from file GOOGLE_APPLICATION_CREDENTIALS.json: Error: ENOENT: no such file or directory, open 'GOOGLE_APPLICATION_CREDENTIALS.json'
The thing is that if I use the credentials I generated for my project it will work with the real Firestore instance instead of the emulator.
How should I make credentials for my emulated services?
If you are using Firebase Functions emulator as well then Admin SDK will connect to all the running emulators e.g. if only Auth emulator is running then it'll use the emulator and connect to production for other services like Firestore. You can explicitly set the FIRESTORE_EMULATOR_HOST environment variable and Admin SDKs will use the emulator then.
Checkout the documentation for more information.

Firebase initializeApp with emulators without production config

I am able to connect to Firebase firestore emulator from a create-react-app app locally using the instructions here. The example code simply includes a comment like this:
// Firebase previously initialized using firebase.initializeApp().
The API reference for initializeApp describes only one way of using it - by passing production configuration to initializeApp and that's the way I got it to work.
However, I am trying to run the app in a self-contained docker environment for the purpose of continuous integration. I do not want any config related to production in this version of the build. By production, I mean any reference that might count towards firebase billing. Is there a way to call initializeApp without production reference? Or are there other ways to handle CI builds?
After some testing, you should initialize app with any string on apiKey:
initializeApp({
apiKey: 'API KEY', // You can set any string here
projectId: 'PROJECT ID HERE', // Optional, you can use here same from .firebaserc
})
We need to use a demo app for this purpose, as explained in this answer. Once we start the emulators described in that answer, initializeApp can be invoked like so:
initializeApp({
projectId: "demo-test",
})
The projectId used in here need to match the one used when starting up the emulator and it needs to start with demo. This ensures there is no way for the app to connect to production services accidentally.

Firebase Emulator request to Google Cloud Speech to Text Api denied

I would like to test the Google Cloud Speech-to-Text API from within Firebase Emulators. I currently have a trigger set on Firebase Storage that automatically gets fired when I upload a file via the Emulator Storage UI. This makes a request to the Speech to Text API, but I keep getting a permission denied error, as follows:
Error: 7 PERMISSION_DENIED: Cloud Speech-to-Text API has not been used in project 563584335869 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/speech.googleapis.com/overview?project=563584335869 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
I understand that project 563584335869 is the Firebase Cli project.
I have set the following environment variables when starting the emulator:
export GCLOUD_PROJECT=my-actual-glcloud-project-id && export FIREBASE_AUTH_EMULATOR_HOST='localhost:9099' && export GOOGLE_APPLICATION_CREDENTIALS=./path/to/service-account.json &&
firebase emulators:start
The service_account.json key file is associated with a service_account that has the following roles, as demonstrated by running
gcloud projects get-iam-policy my_project_id --flatten="bindings[].members" --format='table(bindings.role)' --filter="bindings.members:serviceAccount:my_service_account#my_project_id.iam.gserviceaccount.com"
ROLE
roles/speech.admin
roles/storage.admin
roles/storage.objectAdmin
roles/storage.objectCreator
roles/storage.objectViewer
Since the credentials for the service account I am using should have admin access to the speech to text api, why do I keep getting a permission denied error when running from the emulator, and how can I fix it?
The project id 563584335869 is not yours. It is firebase-cli cloud project’s project-id. In this case, the problem is arising because you have to set your own configuration using your credentials or your key.
You can see below a code for NodeJS which I found in github[1] where it shows how to configure your authentication to use the API.
// Imports the Google Cloud client library
const textToSpeech = require('#google-cloud/text-to-speech');
// Create the auth config
const config = {
projectId: 'grape-spaceship-123',
keyFilename: '/path/to/keyfile.json'
};
// Creates a client
const client = new textToSpeech.TextToSpeechClient(config);
[1]https://github.com/googleapis/nodejs-text-to-speech/issues/26
EDIT
There are different ways to set up your authentication for speech to text. One way to resolve this problem would be to add the same auth configuration as the Text-to-Speech and it should look something like this in your code.
// Imports the Google Cloud client library
const speech = require('#google-cloud/speech');
// Create the auth config
const authconfig = {
projectId: 'grape-spaceship-123',
keyFilename: '/path/to/keyfile.json'
};
// Creates a client
const client = new speech.SpeechClient(authconfig);
Another way to solve this problem according to this Google Cloud Documentation[2] is to setup your authentication.
[2]https://cloud.google.com/speech-to-text/docs/libraries#setting_up_authentication

How can I access the Hacker News API using the Firebase SDK?

The Hacker News API documentation says:
If you can use one of the many Firebase client libraries, you really should. The libraries handle networking efficiently and can raise events when things change. Be sure to check them out.
It doesn't specify how to do that though. How can I use the Firebase client libraries to interact with the Hacker News API, to gain more efficient networking and support for listening for events?
You can interact it with it using the Realtime Database API. Set the databaseURL to https://hacker-news.firebaseio.com, and you can make queries using the Firebase client libraries. The paths are the same as the paths in the API, without the .json file extension. For example, this would get data for the user jl using the web client:
var config = {
databaseURL: "https://hacker-news.firebaseio.com",
};
firebase.initializeApp(config);
var database = firebase.database();
console.log((await database.ref("v0/user/jl").get()).val());

Accessing firestore from self-hosted server

I need to be able to access (read, write) firestore from my self-hosted server (not on gcloud).
I also need to reserve write permissions to the app hosted on my self-hosted server, and allow noone else to be able to write to the server, so the security rules for write applications are denied by default.
According to this document:
https://firebase.google.com/docs/firestore/client/libraries#server_client_libraries
using a service account should allow me to be able to access all firebase products, including firestore, without any restrictions.
But, as soon as I restrict the security rules, I am unable to write to firestore from my service, instantiated with service account credentials following the steps in this documentation:
https://firebase.google.com/docs/admin/setup#initialize-sdk
I get the following error:
PERMISSION_DENIED: Missing or insufficient permissions.
What do I have to do to allow my application to write to firestore from my own servers?
Update:
I am using java for my backend applications.
Servers (or cloud functions) are secure environment which can be accessed only by you and people you have authorized. You don't actually use the Firebase Client SDKs in a server. Instead you use the Firebase Admin SDK. It uses a service account and has privileged access to your Firebase Project.
What does privileged access mean?
The documentation has explained it all but long story short it has complete access like you to the project. It does not follow any security rules.
If you are implementing the Admin SDK which will deal with API requests coming from your clients then make sure you authenticate them. To do so you would ideally pass the Firebase ID Token from your frontend to the API and verify
it using the Admin SDK which returns a decoded token object containing UID, custom claims and some metadata about that user.
I'm not sure which language you use but here's a simple getting started for NodeJS:
// Install the Admin SDK
npm install firebase-admin
// index.js
const admin = require("firebase-admin")
const path = require("path");
admin.initializeApp({
credential: admin.credential.cert("path/to/key")),
databaseURL: "https://<project-id>.firebaseio.com/"
})
const firestore = admin.firestore()
const auth = admin.auth()
// firebase.firestore() and firebase.auth() in client SDKs
Rest of the syntax is mostly the same as Client SDK.
You can create a service account from the project settings.
The issue that I was facing has already been reported here:
https://github.com/googleapis/java-firestore/issues/431
The fix was an odd one, and cannot be explained without going deep into the SDK and how it works, which I did not have time to check:

Resources