Use firebase auto SDK setup with Webpack - firebase

I am creating a web app that uses Vue webpack with firebase. I would like to have my firebase credentials automatically change when i use firebase use <some_alias> on the firebase cli. In other projects, this simply meant including the /__/firebase/init.js file of firebase hosting. In this project, I am using the npm firebase library and can load in a specific firebase set of credentials with
import firebase from 'firebase'
var config = {
apiKey: '...',
authDomain: '...',
databaseURL: '...',
projectId: '...',
storageBucket: '...',
messagingSenderId: '...'
}
firebase.initializeApp(config)
export default {
database: firebase.database,
storage: firebase.storage,
auth: firebase.auth
}
However, this does not get my credentials based on my current firebase workspace. Instead, I would like something like
import firebase from 'firebase'
const fbcli = require('firebase-tools');
export const getFirebaseInstance = () => {
return fbcli.setup.web().then(config => {
firebase.initializeApp(config)
return firebase
});
}
though synchronous. Is there any way to synchronously load in my firebase credentials?

This was solved by checking window.location.host when in the prod environment and having a production config object if the host was our production hostname and reading from the values of a configuration file otherwise.

Try using fs.writeFileSync as described in this example from a firebase blog post about reading credentials:
const fbcli = require('firebase-tools');
const fs = require('fs');
// by default, uses the current project and logged in user
fbcli.setup.web().then(config => {
fs.writeFileSync(
'build/initFirebase.js',
`firebase.initializeApp(${JSON.stringify(config)});`
);
});

Related

Fetching from Firestore URL shows 404 - URL not right?

I am using Next.js to fetch data from my Firestore Database, but I keep getting an error in the console, stating that GET (FirestoreDatabaseURL) 404 (not found).
When I try any other json database such as myfakestore or jsonplaceholder, my code works (I tried both getServerSideProps and fetching with UseState), works beautifully. But not from my own database. Tried with Postman, but it won't work either.
I have tried to find different ways to get the database URL, but I am only finding this one format:
https://PROJECTID.firebaseio.com
The server is in us-central, which also helps determine the URL.
While testing around, I have gotten the error FetchError: invalid json response body at https://PROJECTID.firebaseio.com/ reason: Unexpected token F in JSON at position 0
Which I came to find out that it's not actually returning json, but HTML.
Just for context, this is my working code:
const [showProducts, setShowProducts] = useState()
const apiData = 'https://celeste-73695.firebaseio.com/'
let displayProducts
function pullJson () {
fetch(apiData)
.then(response => response.json())
.then(responseData => {
displayProducts = responseData.map(function(product){
return (
<p key={product.id}>{product.title}</p>
)
})
console.log(responseData)
setShowProducts(displayProducts)
})
//return
}
useEffect(() => {
pullJson()
},[])
And my firebase.js file
import firebase from 'firebase';
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "***",
authDomain: "***",
projectId: "***",
storageBucket: "***",
messagingSenderId: "***",
appId: "***",
measurementId: "***"
};
const app = !firebase.apps.length
? firebase.initializeApp(firebaseConfig)
: firebase.app();
const db = app.firestore();
export default db;
Can anybody point me in the right direction?
Thanks in advance.
The databaseURL property is for the Firebase Realtime Database, which you probably didn't create yet. The databaseURL property is not necessary to use Firestore though, so you should be able to access that with just the configuration data you have.
You may have created the realtime database but not have configured it with firebase config. I recommend you to go through this documentations for the realtime database.
To configure the firebase firestore you need to do the following:
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
// ...
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// Initialize Cloud Firestore and get a reference to the service
const db = getFirestore(app);
And make sure to export the db reference as will be used in your project.
After that you can start using the firestore like documented here as you have tried to use it with URL you may have to change the implementation for using it like shown in above documentations

WebConfig doesn't return measurementId

I am trying to enable firebase analytics in my existing firebase project. The project is a static React website that only uses Firebase hosting.
Following this get start tutorial, I am getting the following error in my console:
Ignored "config" command. Invalid arguments found
Searching how to solve this problem, I found this comment and checked that my webConfig get request is not returning the measurementId. However I couldn't find any info about how to correct it.
//firebase.js
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAnalytics} from "firebase/analytics";
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "{ApiKey}",
authDomain: "{projectId}.firebaseapp.com",
projectId: "{projectId}",
storageBucket: "{projectId}.appspot.com",
messagingSenderId: "{messagingSenderId}",
appId: "{appId}",
measurementId: "{measurementId}",
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const analytics = getAnalytics(app);
WebConfig call (Http 200, Get):
response:
{
"projectId": "{projectId}",
"appId": "{appId}",
"storageBucket": "{projectId}.appspot.com",
"authDomain": "{projectId}.firebaseapp.com",
"messagingSenderId": "{messagingSenderId}"
}
Is there any config that I am missing? what should I do to make it work?
There could be something wrong with the stream for your web app that’s why the measurementId is not being configured. You could try to unlink and relink to your Google Analytics integration which usually resolves any broken integration. Make sure that the currently linked GA property is the one you’re going to use for relinking to avoid losing your data.

Nuxt + Firebase - Correct way to handle environment variables

I have been trying to develop a fully functional, reusable firebase authentication app however after looking online at multiple different solutions, I have developed the below which works perfectly but from my understanding there is no way to protect the API keys/sensitive data? Is there anyway to use environment variables on the plugins/firebase.js file?
The nuxt/firebase docs suggests declaring them within the nuxt.config.js file? But when following the docs and trying to install firebase & #nuxtjs/firebase I keep running into errors. NPM error when I am trying to install #nuxtjs/firebase
Is there any definitive/working best practise to follow when working with Nuxt & Firebase?
~plugins/firebase.js
import firebase from 'firebase/app';
import 'firebase/auth'
import 'firebase/firestore'
import 'firebase/storage'
const firebaseConfig = {
apiKey: "xxxx",
authDomain: "xxxx",
projectId: "xxxx",
storageBucket: "xxxx",
messagingSenderId: "xxxx",
appId: "xxxx"
};
firebase.apps.length ? firebase.initializeApp(firebaseConfig) : ''
export const auth = firebase.auth()
export const google = new firebase.auth.GoogleAuthProvider()
export const storage = firebase.storage()
export default firebase
~/plugins/fireauth.js
import { auth } from '~/plugins/firebase.js'
export default (context) => {
const { store } = context
return new Promise((resolve, reject) => {
auth.onAuthStateChanged(user => {
console.log(user);
store.dispatch('setUser', user)
resolve(user)
}, err => {
reject(err)
})
})
}
Update to #Kissu
The environment variables are now working as per #kissu's comments below - however the app is now crashing because the initializeApp() is not being run.
Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app-compat/no-app).
~/plugins/firebase.js
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth'
import 'firebase/compat/firestore'
import 'firebase/compat/storage'
export default ({ $config }) => {
const firebaseConfig = {
apiKey: $config.firebaseConfig.apiKey,
authDomain: $config.firebaseConfig.authDomain,
projectId: $config.firebaseConfig.projectId,
storageBucket: $config.firebaseConfig.storageBucket,
messagingSenderId: $config.firebaseConfig.messagingSenderId,
appId: $config.firebaseConfig.appId
}
!firebase.apps.length ? firebase.initializeApp(firebaseConfig) : ''
}
export const auth = firebase.auth()
export const google = new firebase.auth.GoogleAuthProvider()
export const storage = firebase.storage()
Resources:
https://firebase.nuxtjs.org/
https://dev.to/drewclem/building-user-accounts-with-nuxt-vuex-and-firebase-2o6l
In your Firebase Config, you can use local environment variables (from your .env file) using process.env.VUE_APP_:
// ~/plugins/firebase.js
const firebaseConfig = {
apiKey: process.env.VUE_APP_FIREBASE_apiKey,
authDomain: process.env.VUE_APP_FIREBASE_authDomain,
projectId: process.env.VUE_APP_FIREBASE_projectId,
storageBucket: process.env.VUE_APP_FIREBASE_storageBucket,
messagingSenderId: process.env.VUE_APP_FIREBASE_messagingSenderId,
appId: process.env.VUE_APP_FIREBASE_appId,
measurementId: process.env.VUE_APP_FIREBASE_measurementd,
};
But be sure to set your Variables in your .env file like this:
// ~/.env
// NOTE: THIS FILE IS NOT COMMITTED TO CODE REPOSITORY / GITHUB AND SHOULD BE IGNORED BY DEFAULT IN YOUR `.gitignore` FILE
// NOTE: For Vue.js environment variables, you must prefix them with `VUE_APP_`
VUE_APP_FIREBASE_apiKey=
VUE_APP_FIREBASE_authDomain=
VUE_APP_FIREBASE_projectId=
VUE_APP_FIREBASE_storageBucket=
VUE_APP_FIREBASE_messagingSenderId=
VUE_APP_FIREBASE_appId=
VUE_APP_FIREBASE_measurementId=
Where after the = you put your secret keys and ID's. NOTE: Be sure to leave NO SPACE between the = and your key. For example:
VUE_APP_FIREBASE_apiKey=YOUR.KEY.HERE
...
You can read more documentation on VUE_APP Environment Variables here: https://cli.vuejs.org/guide/mode-and-env.html#environment-variables
This .env file should not be committed to Github, or your code repository. Instead, set these variables on your production environment. For example, if you are using Netlify or Heroku, you will want to set Environment Variables with the EXACT same names like VUE_APP_FIREBASE_apiKey and set its value to be equal to your Key.
If using Netlify, set your Environment Variables in your Build & Deploy Site Settings:
https://app.netlify.com/sites/{{YOUR_SITE_HERE}}/settings/deploys#environment

GitHub continuous deployment to Firebase hosting and env variables

I am currently working on a React application with Firebase initialised. I am initialising my React App with Firebase by doing the following:
import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/firestore'
const app = firebase.initializeApp({
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_FIREBASE_APP_ID
})
const db = firebase.firestore()
export { db, app }
For obvious reasons, I do not want to push my env file to GitHub. But if I do not, my application build fails. I am wondering how I can configure GitHub to house my env variables and for my production build to use the GitHub env variables. I have attempted to set up a GitHub build workflow, which contains the env variables, but my build still seems to fail.
On a separate note, I am curious how much of a security risk it is for my Firebase config to be exposed. I read if my application is using an email/password sign-in method, I should protect these variables. Any advice, suggestions, critiques would be much appreciated.
Just use GitHub Actions with secrets and echo with the runner:
- name: 🗄️ Provide credentials
id: firebase-credentials
run: echo 'const app = firebase.initializeApp({apiKey: "${{ secrets.FIREBASE_API_KEY }}", ... })' > ./some.js
You can use Firebase Cloud Functions and set an environment variable in the terminal:
firebase functions:config:set someservice.key="API KEY" someservice.id="CLIENT ID"
For example, to set up the Cloud Function for Firebase:
firebase init functions
npm install --save firebase-functions#latest
npm install -g firebase-tools
You can then access the variables from a function:
const functions = require('firebase-functions');
const request = require('request-promise');
exports.userCreated = functions.database.ref('/users/{id}').onWrite(event => {
let email = event.data.child('email').val();
return request({
url: 'https://someservice.com/api/some/call',
headers: {
'X-Client-ID': functions.config().someservice.id,
'Authorization': `Bearer ${functions.config().someservice.key}`
},
body: {email: email}
});
});

Firebase: Update Firestore Fails If Document Does Not Exist [duplicate]

This is my very basic Cloud Function:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const db = admin.firestore()
exports.createdNewAccount = functions.auth.user().onCreate(event => {
return db.collection('users').doc(event.data.uid).update({
"creationDate" : Date.now()
})
})
And I get the error
Error: no entity to update: app
What is wrong with my code?
Most likely, the document for event.data.uid does not exist. The documentation for update() states:
The update will fail if applied to a document that does not exist.
Use set() instead.
I faced a similar error when testing my app locally with the Firebase emulator. My firebase config file looked like:
import firebase from "firebase";
import "firebase/firestore";
const firebaseConfig = {
apiKey: <FIREBASE_API_KEY>,
authDomain: <FIREBASE_AUTH_DOMAIN>,
databaseURL: <FIREBASE_DB_URL>,
projectId: <FIREBASE_PROJECT_ID>,
storageBucket: <FIREBASE_STORAGE_BUCKET>,
messagingSenderId: <FIREBASE_MSG_SENDER_ID>,
appId: <FIREBASE_APP_ID>,
measurementId: <FIREBASE_MEASUREMENT_ID>,
};
// Initialize Firebase
const firebaseApp = firebase.initializeApp(firebaseConfig);
// for local instances, use the emulator to connect the frontend to firestore & functions
if (location.hostname === "localhost") {
firebase.firestore().settings({
host: "localhost:8080",
ssl: false,
});
firebase.functions().useFunctionsEmulator("http://localhost:5001");
}
Turns out my local Firestore database (expected to be running at localhost:8080) wasn't being hit. So my cloud functions were trying to write to a non-existent db. The underlying issue was that I also had my backend initializing to a different database:
// functions/index.js
const admin = require("firebase-admin");
var serviceAccount = require("./serviceAccount.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://other-firebase-project-id.firebaseio.com",
});
The solution (originally adapted from a Fireship tutorial) was to remove this [incorrect] re-initialization of the database altogether:
// functions/index.js
...
admin.initializeApp();
...
After all, according to the docs, we can initialize the Firebase Admin SDK without parameters since the FIREBASE_CONFIG environment variable is included automatically in Cloud Functions for Firebase functions that are deployed via the Firebase CLI.
FWIW, also be sure to set the correct Firebase project on the CLI. Doing so with this allows the Firebase CLI to hook Functions/Firestore to the right project:
firebase use <desired-firebase-project-id>
If you have multiple Firebase projects, you can list them out with: firebase projects:list

Resources