Need help in understanding Firebase config security - firebase

If one integrates this config in JS, won't it be a security concern as any one can open the JS file, get access to this details and access my firebase DB?
var config = {
apiKey: "xxxx",
authDomain: "xxx.firebaseapp.com",
databaseURL: "https://xxx.firebaseio.com",
storageBucket: "xxx.appspot.com",
messagingSenderId: "0000"
};
How does one make sure it's secure?

That's just so the client can identify your app. Even the apiKey is more like a reference and less like a secret password so don't worry. You can use this to instantiate many apps inside a single file. (see https://firebase.google.com/docs/web/setup)
// Intialize the "[DEFAULT]" App
var mainApp = firebase.intializeApp({ ... });
// Intialize a "Secondary" App
var secondaryApp = firebase.initializeApp({ ... }, "Secondary");
...
mainApp.database().ref("path/to/data").set(value);
secondaryApp.database().ref("path/to/data").set(anotherValue);
Now, the heart of Firebase security are the Firebase Realtime Database Rules. Learn them here:
https://firebase.google.com/docs/database/security/
The Firebase Realtime Database Rules are expressed in a JSON-like format, so you should be creating some for yourself in no time!

Related

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.

admin but not storage pointing to the right project

In my project I have setup a dev and production environment by doing this:
const firebaseConfig =
process.env.FUNCTIONS_EMULATOR === "true"
? {
apiKey: process.env.FIREBASE_DEV_KEY,
authDomain: "myapp-dev.firebaseapp.com",
projectId: "myapp-dev",
storageBucket: "myapp-dev.appspot.com",
messagingSenderId: "...",
appId: "...",
measurementId: "...",
}
: {
apiKey: process.env.FIREBASE_PROD_KEY,
authDomain: "myapp-production.firebaseapp.com",
projectId: "myapp-production",
storageBucket: "myapp-production.appspot.com",
messagingSenderId: "...",
appId: "...",
measurementId: "...",
}
admin.initializeApp(firebaseConfig)
Then firestore points to the right project because it was initialized from admin like above:
const firestore = admin.firestore()
However, I am now trying to listen to storage uploads.
And by default, it is listening to my production app. I need to listen to uploads to my dev project.
The problem arises since the storage listener is coming from functions and not admin (which was initialized with the right config).
How can I "initialize" the storage listener (below) so that it listens to the dev project?
exports.generateThumbnail = functions.storage
.object()
.onFinalize(async (object) => {})
Is there maybe a way to attach a listener to admin.storage()?
I'm not sure but it seems like you are using the Client SDK configuration in the Cloud function. The Admin SDK uses a service account instead of the client config.
The FIREBASE_CONFIG environment variable is included automatically in Cloud Functions for Firebase functions that were deployed via the Firebase CLI.
That being said, you just need to initialize the Admin SDK as shown below:
import * as admin from 'firebase-admin';
admin.initializeApp()
Talking about the environments, I can clearly see that you have two different projects for different environments. In that case you would have to deploy the functions to both the project separately because the Admin SDK which uses service account for the dev project will be listening for changes in the dev project only
Other option would be initializing the Admin SDK twice as mentioned in the documentation.
You can also consider using the same Firebase project for both dev and production but use different buckets for them. That way you can listen to those buckets separately. For listening to a specific bucket, specify it's name:
const devFunction = functions.storage.bucket('dev-bucket').object().onFinalize(async (object) => {
//...
})
const prodFunction = functions.storage.bucket('prod-bucket').object().onFinalize(async (object) => {
//...
})

How to request notification permission again on web through flutter

I have integrated notifications for flutter web, its working fine when i give permission for the first time, but lets say user has denied it so is there any way to request notifications permission again to get token in dart files from javascript files ?
importScripts('https://www.gstatic.com/firebasejs/7.15.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.15.0/firebase-messaging.js');
var firebaseConfig = {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
};
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
icon: 'favicon.png'
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
You can follow a similar permission call posted as an Answer in this post. For your use case, you'll need to use push permission since Firebase Cloud Messaging for web needs Push API support as mentioned in the official docs
Use dart:html package for the permission requests using Web API. Import the dart:html package, and set a prefix. In this sample, we used 'html'
import 'dart:html' as html;
Create a helper method to check for push permissions.
checkPushPermission() async {
var pushPermission = await html.window.navigator.permissions.query({"name": "push"});
print('push permission: ${pushPermission.state}')
}
Call checkPushPermission() to verify the current push permission state, and it should display the relevant permission dialog.
checkPushPermission();
Be reminded that FlutterFire Cloud Messaging is yet to be fully supported for Web, and there could be quirks in its current state. Also, be aware of Web API's browser compatibility.
I did not test it myself but it seems you should call the browser "requestPermission" API:
https://developer.mozilla.org/en-US/docs/Web/API/Notification/requestPermission
https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API
For Flutter I have seen there is this call in "dart:html" package:
https://api.flutter.dev/flutter/dart-html/Notification/requestPermission.html

How to save firebase config parameters in environment variables in vuejs when using firebase hosting

I'm new to firebase. I've employed it into my vuejs project. How do i save the firebase config parameters into environment variables. Or is there a better way to achieve this.
Use .env.js files in vue
This is actually not really needed as you can also store the config directly in the main.js file. Also, these firebase config data is public and needs not to be protected. Still here is how you do it.
In your prod.env.js file (located for my setup under the folder config) add
'use strict'
module.exports = {
NODE_ENV: '"production"',
FIREBASE_API_KEY: '"APIKEY"',
FIREBASE_AUTH_DOMAIN: '"YOURID.firebaseapp.com"',
FIREBASE_DATABASE_URL: '"YOURURL"',
FIREBASE_PROJECT_ID: '"YOURID"',
FIREBASE_STORAGE_BUCKET: '""',
FIREBASE_MESSAGING_SENDER_ID: '"YOURSENDERID"',
FIREBASE_APP_ID: '"YOURAPPID"',
}
In main.js call the env variables with process.env.VARIABLENAME.
Here is the setup for firebase:
const firebaseConfig = {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.FIREBASE_DATABASE_URL,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.FIREBASE_APP_ID,
};
you can always create a new file that contains all the configuration settings and gitignore that file hence making it secure.
It depends only on your project structure.
Just import this file wherever it is needed without compromising your security

Use firebase auto SDK setup with Webpack

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)});`
);
});

Resources