Firebase script code is shown in console [duplicate] - javascript

This question already has answers here:
Is it safe to expose Firebase apiKey to the public?
(10 answers)
Closed 4 years ago.
I'm quite new to Firebase in general and I have some questions which I'm not sure if they are an issue or not.
First I set up my API keys and such
<script>
firebase.initializeApp({
apiKey: '#####',
authDomain: '#####',
projectId: '####'
});
// Initialize Cloud Firestore through Firebase
var db = firebase.firestore();
</script>
And than I went and used the example given by google
<script>
var docRef = db.collection("MyTable").doc("person1");
docRef.get().then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch(function(error) {
console.log("Error getting document:", error);
});
</script>
And it worked i got the stuff that I needed. Buy my main question is isn't this unsafe?
I opened the Developer Console and i inspected the scripts to see what's going on and I saw that it shows everything , my database name , the collection I'm accessing and so on.
What makes a random person just copying my code and running it on their side? Is there a fix to this is it meant to work like this?
As I said I'm new to this so maybe I'm missing something here.

You are unable to whitelist domains for your database. Keep in mind as a public cloud hosted database, public really means public. That said there are a few things you can do;
Use firebase cloud functions for anything you want to keep out of the client.
Use /__/firebase/init.js in your web client which will configure and initialize your firebase instance without it being explicitly loaded onto the page - Keep in mind users can still get the info by following the JS link.
If your users are authenticated then can use database rules to make sure they only logged in users see data { "rules": { ".read": "auth !== null" } } , or that the logged in user can see their own data. Check here for more info https://firebase.google.com/docs/firestore/security/get-started#writing_rules
If you setup rules to require your users to be signed in, you can use google auth to whitelist your domain. This will ensure only your users can view your data and also that it is only via your client. For more info in writing queries with rules applied, see this page https://firebase.google.com/docs/firestore/security/rules-query

Related

Vue 3 Firebase Auth get *any* user data by id? [duplicate]

This question already has an answer here:
How to get FirebaseUser from a uid?
(1 answer)
Closed 8 months ago.
New to vue/firebase. I was able to lookup how to pull up “current user” data from auth no problem but trying to write a js composable that I can pass in any user id (not necessarily current user) and it will return the user object or at least displayName.
All the docs/vids I can find on the topic reference getting info on *current user *only not another user. From the Google Docs it says I should be able to do this in the "Retrieve user data" section. Closest model to Vue code-wise seems to be “Node.Js” but it isn't working.
Here's what I've got in getUserById
import { getAuth } from 'firebase/auth'
const getUserById = (u) => { // u = user id
const userData = null
getAuth()
.getUser(u)
.then((userRecord) => {
// See the UserRecord reference doc for the contents of userRecord.
console.log(`Successfully fetched user data: ${userRecord.toJSON()}`);
userData = userRecord
})
.catch((error) => {
console.log('Error fetching user data:', error);
});
return { userData }
}
export default getUserById
The error I get is getUser is not a function. I tried adding getUser to the import but same error.
There is no way to look up information about just any user by their UID in the client-side APIs of Firebase as that would be a security risk. There is an API to look up a user by their UID in the Admin SDK, but that can only be used on a trusted environment (such as your development machine, a server you control, or Cloud Functions/Cloud Run), and not in client-side code.
If you need such functionality in your app, you can either wrap the functionality from the Admin SDK in a custom endpoint that you then secure, or have each user write information to a cloud database (such as Realtime Database or Firestore) and read it from there.
Also see:
How to get FirebaseUser from a uid?
Firebase get user by ID
Is there any way to get Firebase Auth User UID?

React Native Could not reach Cloud Firestore backend

I was previously using firebase realtime database however now want to switch over to Cloud Firestore but am getting the below error, even when authenticated. I'm currently using Android Simulator, tried disabling my realtime database but cannot find a solution.
Firebase v5.4.2
[2018-09-02T12:53:42.064Z] #firebase/firestore:', 'Firestore (5.0.4):
Could not reach Cloud Firestore backend. Backend didn't respond within
10 seconds. This typically indicates that your device does not have a
healthy Internet connection at the moment. The client will operate in
offline mode until it is able to successfully connect to the backend.
My config is setup:
{
"apiKey": "apiKey",
"authDomain": "authDomain.firebaseapp.com",
"databaseURL": "https://databaseURL.firebaseio.com",
"projectId": "projectID",
"storageBucket": "storageBucket.appspot.com",
"messagingSenderId": "messagingSenderId"
}
As per docs I'm adding a users collection. Note that I do not get into the .then or the .catch statement even if I setup a users collection manually against the database.
onTestPress() {
console.log("onTestPress");
var db = firebase.firestore();
//console.log(db);
const settings = { timestampsInSnapshots: true };
db.settings(settings);
db.collection("users").add({
first: "Ada",
last: "Lovelace"
}).then(function (docRef) {
console.log("adding document: ", docRef.id);
}).catch(function (error) {
console.log("Error adding document: ", error);
});
db.collection("users").get().then((querySnapshot) => {
console.log(`querySnapshot: ${querySnapshot}`)
querySnapshot.forEach((doc) => {
console.log(`${doc.id} => ${JSON.stringify(doc.data())}`);
});
});
}
This is from Android Logcat you can see the .get() query returns the local copy. Only thing suspicious is the duplicate layer name?
09-02 14:05:37.811 2987-4016/com.myApp I/ReactNativeJS: onTestPress
09-02 14:05:47.837 2987-4016/com.myApp E/ReactNativeJS: '[2018-09-02T13:05:47.837Z] #firebase/firestore:', 'Firestore (5.0.4): Could not reach Cloud Firestore backend. Backend didn\'t respond within 10 seconds.\nThis typically indicates that your device does not have a healthy Internet connection at the moment. The client will operate in offline mode until it is able to successfully connect to the backend.'
09-02 14:05:47.849 2987-4016/com.myApp I/ReactNativeJS: querySnapshot: [object Object]
09-02 14:05:47.849 2987-4016/com.myApp I/ReactNativeJS: 3jifIc5kyEkGU4Bzvau9 => {"first":"Ada","last":"Lovelace"}
09-02 14:05:47.858 1431-1431/? D/SurfaceFlinger: duplicate layer name: changing com.myApp/com.myApp.MainActivity to com.myApp/com.myApp.MainActivity#1
09-02 14:05:47.931 2987-3021/com.myApp D/EGL_emulation: eglMakeCurrent: 0x9d7857e0: ver 3 0 (tinfo 0x9d783540)
Here's my import:
import firebase from "firebase";
import '#firebase/firestore'
Rules setup which should allow read and write?
// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this rule set in production; it allows
// anyone to overwrite your entire database.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
I'm really not sure what else I can check so any advise would be greatly appreciated!
I also had this issue. The warning should appear after 10 seconds. but in my case, it appears when i load the component, without timeout. because my laptop's time in not correct. I did correct time and still had that issue. so i had to turn on "Set time automatically" and "Set time zone automatically" in "Date & time" settings in windows. everything works out for me.

Administrator Views for a Firebase Web Application: How To

My Firebase web app requires administrator access, i.e., the UI should show a few things only for admins (an 'administrator' section). I came up with the below as a means to authorize the UI to display the admin section for valid admins only. My question is, good or bad? Is this a sound means of authorizing? ...so many ways to do this. This particular way requires me to configure admins in the security rules (vs in a node/tree in a db/firestore)
My idea is that if the .get() fails due to unauthorized access, I tell my app logic the user is not an admin, if the .get() succeeds my logic shows the 'admin' sections. Of course, the 'sections' are just HTML skeletons/empty elements populated by the database so even if the end user hacks the JS/logic, no real data will be there - only the empty 'admin section' framework.
function isAdmin(){
return new Promise(function(resolve, reject){
var docRef = firebase.firestore().collection("authorize").doc("admin");
docRef.get().then(function(result) {
if (result) {
resolve (true);
}
}).catch(function(error) {
resolve (false);
});
});
}
The firestore rule specifies the 'admins' by UID.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid == "9mB3UxxxxxxxxxxxxxxxxxxCk1";
}
}
}
You're storing the role of each user in the database, and then looking it up in the client to update its UI. This used to be the idiomatic way for a long time on realtime database, and it still works on Firestore.
The only thing I'd change is to have the rules also read from /authorize/admin, instead of hard-coding the UID in them. That way you only have the UID in one place, instead of having it in both the rules and the document.
But you may also want to consider an alternative: set a custom claim on your admin user, that you can then read in both the server-side security rules (to enforce authorized access) and the front-end (to optimize the UI).
To set a custom claim you use the Firebase Admin SDK. You can do this on a custom server, in Cloud Functions, but in your scenario it may be simpler to just run it from your development machine.
Detailed How To: Firebase has what's called Custom Claims for this functionality as detailed in their Control Access with Custom Claims and Security Rules. Basically, you stand up a separate node server, install the Firebase AdminSDK:
npm install firebase-admin --save
Generate/Download a Private Key from the Service Accounts tab in the Firebase Console and put that on your node server. Then simply create a bare bones node app to assign Custom Claims against each UID (user) that you wish. Something like below worked for me:
var admin = require('firebase-admin');
var serviceAccount = require("./the-key-you-generated-and-downloaded.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://xxxxxxxxxxxxxxxxxxxx.firebaseio.com"
});
admin.auth().setCustomUserClaims("whatever-uid-you-want-to-assign-claim-to", {admin: true}).then(() => {
console.log("Custom Claim Added to UID. You can stop this app now.");
});
That's it. You can now verify if the custom claim is applied by logging out of your app (if you were previously logged in) and logging back in after you update your web app's .onAuthStateChanged method:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
firebase.auth().currentUser.getIdToken()
.then((idToken) => {
// Parse the ID token.
const payload = JSON.parse(window.atob(idToken.split('.')[1]));
// Confirm the user is an Admin.
if (!!payload['admin']) {
//showAdminUI();
console.log("we ARE an admin");
}
else {
console.log("we ARE NOT an admin");
}
})
.catch((error) => {
console.log(error);
});
}
else {
//USER IS NOT SIGNED IN
}
});

firebase javascript injection

I want ask something about firebase security. How to handle following situations?
User is creating account with createUserWithEmailAndPassword() function, then i save his username,email,created_at...to realtime db. But what if data are not saved correctly. His account is created and he is logged in automatically but data is not stored.
I have some registration logic... for example unique usernames... so before creating acc i check if this username exist in realtime db. But he still can call createUserWithEmailandPassword() from js console and account is created.
For situation one:
According to the firebase docs (https://www.firebase.com/docs/web/api/firebase/createuser.html), creating a user does not automatically authenticate them. An additional call to authWithPassword() is required first. In order to ensure that a user isn't authenticated without valid data, you could run a check to the server to make sure the data is saved correctly before authenticating.
Edit: Nevermind that; looks like firebase does auto-auth now - take a look at what I wrote below.
Now a concern with this approach would be if your app allowed people to authenticate with an OAuth provider like gmail, then there is no function for creating the user before authenticating them. What you may need to do is pull the user data from the firebase, determine if it's valid, and if its not valid show a popup or redirect that lets the user fix any invalid data.
For situation two:
If you wanted to make sure that in the case of them calling createUserWithEmailAndPassword() from the console a new user is not created, you could try something like this with promises;
var createUserWithEmailAndPassword = function(username, password) {
var promise = isNewUserValid(username, password);
promise.then(function() {
// Code for creating new user goes here
});
}
In this way, you never expose the actual code that makes a new user because it exists within an anonymous function.
I don't think that this could solve the problem entirely though because firebases API would let anyone create an account using something
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.createUser({
email: "bobtony#firebase.com",
password: "correcthorsebatterystaple"
}
(Taken from https://www.firebase.com/docs/web/api/firebase/createuser.html)
If you wanted to make sure that server side you can't ever create a user with the same user name, you'd need to look into firebases's rules, specifically .validate
Using it, you could make sure that the username doesn't already exist in order to validate the operation of creating a username for an account.
Here's the firebase doc on rules: https://www.firebase.com/docs/security/quickstart.html
And this is another question on stack overflow that is quite similar to yours. Enforcing unique usernames with Firebase simplelogin Marein's answer is a good starting point for implementing the server side validation.
First save the user credentials in the realtime database before you create the user:
var rootRef = firebase.database().ref('child');
var newUser = {
[name]: username,
[email]: useremail,
[joined]: date
};
rootRef.update(newUser);
After adding the Usersinfo into the realtime database create a new user:
firebase.auth().createUserWithEmailAndPassword(useremail, userpassword).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
When an error occured while inserting the data in the realtime database, it will skip the createuser function.
This works fine for me, hope this helps!

How to handle user information using firebase simple login for facebook

I am building a webpage using AngularJS and Firebase. I want to use facebook login to connect information on the webpage with the user. Firebase has a version of simple login which I guess is supposed to simplify the login process.
My problem is that I want to access information about the logged in user in a lot of places on my webpage but I can't find a good way to do it.
This is how I started out:
var userInfo = null;
var ref = new Firebase('https://<yourfirebase>.firebaseIO.com/');
var auth = new FirebaseSimpleLogin(ref, function(error, user) {
if(error)
alert("You are not logged in");
else if(user)
{
//store userinfo in variable
userInfo = user;
}
else
//user logged out
});
//do something with userInfo
alert(userInfo.name);
My first thought was to run this at the top of my page and then use the info about the user. The problem is that the code using userInfo (as in e.g. the alert) will always run before the userInfo variable has been filled and userInfo will return undefined/null.
I then proceeded to always create a new firebasesimplelogin object when i want to retrieve user data. Which of course isn't very good. Especially since every created FirebaseSimpleLogin object will be called again whenever another is called or a user logs out, for example.
So my question is, how do I use FirebaseSimpleLogin to handle and use my user information in the best way?
I would have liked some function to getUserInfo() or check isLoggedIn() for example. How do you do this properly?
You can take a look at this example for thinkster. It's based on using simple login with userid/password. http://www.thinkster.io/angularjs/4DYrJRxTyT/7-creating-your-own-user-data-using-firebase.
You can create a function like getLoggedinUser that runs in $rootScope that will allow you to find the user throughout the application.
UPDATE:
Around the middle of October 2014, firebase made some big changes. This method might still work, but it's better to take advantage of the newer version of firebase, specifically getauth and onauth. These methods will allow you to do the same thing without running on the rootScope. https://www.firebase.com/docs/web/guide/user-auth.html#section-login
Please make a constant to use it everywhere in your App like that
.constant('facebookUrl', 'https://rjrestaurantapp.firebaseio.com');
Then in the controller inject this constant "facebookUrl & "$state" as shown below...
.controller('loginCtrl', function($scope,facebookUrl,$state){
and then you only need to give name of the state where you want to redirect after facebook authentication..
var ref = new Firebase(facebookUrl);
$scope.fbLogin = function () {
ref.authWithOAuthPopup("facebook", function(error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
console.log("Authenticated successfully with payload:", authData);
$state.go('restaurant');
}
})
}})
You can see the information in authData object after successfull authentication using facebook ....
please read this doc carefully https://www.firebase.com/docs/web/guide/login/facebook.html
The above is the example of simple login using firebase and for retrieving data for each logged in user, you have to store user information at the time of signin as you know that firebase makes every child with a unique ID .. then you only need to use the offline features of firebase that will find which user is offline and according to that remove the node with the same ID which one is offline, you can find examples in the MANAGING PRESENCE section of the below link ..
https://www.firebase.com/docs/web/guide/offline-capabilities.html

Categories