i have a question about configuration of firebase with a react app. I put all firebase config info in .env file at the top directory as environmental variables. When I tried to use them as process.env.REACT_APP_smth, they all didn't work. Once I replaced the variables to real, raw config info, my app worked. But For sure, it's too dangerous so I don't wanna do it.
Also, the .env file was darker in vs code like mentioning it's not valid or smth.
Anyone knows how to tackle with this issue??
Thanks for your time and effort here in advance.
.env
I replaced REACT_APP_FIREBASE_API_KEY with 123456789.
REACT_APP_FIREBASE_API_KEY = "123456789"
REACT_APP_FIREBASE_AUTH_DOMAIN = "kinnikuhub.firebaseapp.com"
REACT_APP_FIREBASE_DATABASE_URL = "https://kinnikuHub.firebaseio.com"
REACT_APP_FIREBASE_PROJECT_ID = "kinnikuhub"
REACT_APP_FIREBASE_STORAGE_BUCKET = "kinnikuhub.appspot.com"
REACT_APP_FIREBASE_MESSAGING_SENDER_ID = "131675559"
REACT_APP_FIREBASE_APP_ID = "1:131675559:web:3ca3bbad263b6be90ff282"
firebase.js
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
// import { getAnalytics } from "firebase/analytics";
import { addDoc, getDocs, getFirestore } from "firebase/firestore"
import { getAuth, signInWithPopup, GoogleAuthProvider } from "firebase/auth";
import { collection } from "firebase/firestore";
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
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,
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// const analytics = getAnalytics(app);
export const db = getFirestore();
export const auth = getAuth(app);
const provider = new GoogleAuthProvider();
export const signInWithGoogle = () => {
signInWithPopup(auth, provider)
.then((res) => {
console.log(res);
// todo: Why create users table?? To let users have personal info, number of answers and quizzes cretaed, biography, sns links, etc
// todo: 1st, check if res.user exists
const userCollectionRef = collection(db, 'users');
let userExistance = false;
console.log(`currentUser.uid => ${res.user.uid}`)
console.log(userExistance)
const checkUserExists = async () => {
const querySnapshot = await getDocs(userCollectionRef);
querySnapshot.forEach( (doc) => {
// doc.data() is never undefined for query doc snapshots
// console.log(doc.id, " => ", doc.data());
// console.log(`currentUser.uid => ${res.user.uid}`)
if (doc.data().uid === res.user.uid) {
userExistance = true;
// console.log(userExistance)
return 0;
}
});
console.log(userExistance)
// todo: 2nd, add this user to users collection if it doesn't exists
if (userExistance === false) {
console.log(`userExistance is false, meaning this user hasn't been registerd so I am going add the user into users collection!!! ${res.user.displayName}, ${JSON.stringify(res.user)}`)
const addUser = async () => {
const payload = {
username: res.user.displayName,
uid: res.user.uid,
email: res.user.email,
photoURL: res.user.photoURL,
createdAt: new Date(),
bio: "biography",
};
await addDoc(userCollectionRef, payload);
}
addUser();
} else {
console.log('This user has been already registered!! So glad he/she keeps using this app!!')
}
}
checkUserExists();
}).catch((err) => {
console.log(err);
})
}
// export const AuthState = () => {
// const [userInfo, setUserInfo] = useState({})
// onAuthStateChanged(auth, (user) => {
// if (user) {
// const username = user.displayName;
// const uid = user.uid;
// const email = user.email;
// const photoURL = user.photoURL
// // const emailVerified = user.emailVerified
// setUserInfo({username, uid, email, photoURL});
// console.log(`username => ${username}`)
// console.log(`uid => ${uid}`)
// console.log(`email => ${email}`)
// console.log(`photoURL => ${photoURL}`)
// // console.log(`emailVerified => ${emailVerified}`)
// return userInfo;
// } else {
// console.log("no user signed in")
// }
// })
// }
// sendEmailVerification(auth.currentUser)
// .then(() => {
// console.log('email verification sent!')
// })
##.gitignore
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
.env
npm-debug.log*
yarn-debug.log*
yarn-error.log*
Background:
Yesterday, I initialized my pc to install Monterey in my macbook air and files in the pc were all gone. Then, I git-cloned the repo of this app.
You have everything correct from what I see except the file naming itself. I too struggled to try to get this to work until I made this simple change:
Try renaming your 'firebase.js' file to 'firebase.config.js', this will read your process.env variables as actual variables.
The variable values in .env should not be enclosed in the quotation marks. Remove the quotation marks.
I also had the same issue. I solved the issue by only replacing the projectID with the actual variable.
ex:-
const firebaseConfig = {
apiKey: process.env.REACT_APP_APIKEY,
authDomain: process.env.REACT_APP_AUTHDOMAIN,
projectId: "personal-portfolio-f1e9f",
storageBucket: process.env.REACT_APP_STORAGEBUCKET,
messagingSenderId: process.env.REACT_APP_MESSAGINGSENDERID,
appId: process.env.APPID,
measurementId: process.env.MEASUREMENTID
};
Related
i'm trying to create an app with firebase firestore and firebase authentication. when i'm adding a document to users collection with add it's not working. but authentication is working. firestore rules are allowed read and write.
firebase configuration
import { initializeApp } from 'firebase/app'
import {
initializeAuth,
getReactNativePersistence
} from 'firebase/auth/react-native';
import AsyncStorage from '#react-native-async-storage/async-storage';
import { apiKeyUrl, apiIdUrl } from './env'
// configuration
const apiKey = apiKeyUrl.apiKey
const apiId = apiIdUrl.apiId
const app = initializeApp(firebaseConfig)
const auth = initializeAuth(app, {
persistence: getReactNativePersistence(AsyncStorage)
});
export { auth }
*/
import firebase from "firebase/compat/app"
import 'firebase/compat/auth'
import 'firebase/compat/firestore'
import { apiKeyUrl, apiIdUrl } from './env'
const apiKey = apiKeyUrl.apiKey
const apiId = apiIdUrl.apiId
const firebaseConfig = {
apiKey: apiKey,
authDomain: ".",
projectId: ".",
storageBucket: ".",
messagingSenderId: ".",
appId: apiId,
measurementId: "."
};
// Initialize Firebase and Firestore
let app
if (firebase.apps.length === 0) {
app = firebase.initializeApp(firebaseConfig);
} else {
app = firebase.app();
}
const db = app.firestore(app)
const auth = app.auth()
export { db, auth }
and
try {
await auth.createUserWithEmailAndPassword(email, password)
.then(_ => {
db.collection('users').add({
userEmail : "aaa",
userId : "asdasd",
userName : "asdasd"
})
})
}catch (err) {
console.log("err : " + err)
}
catch not throwing anything. firebase version is ^9.6.11
Try this it should work
try {
await auth.createUserWithEmailAndPassword(email, password)
.then((user) => {
db.collection('users')
.doc(user.uid)
.set({
userEmail : "aaa",
userId : "asdasd",
userName : "asdasd"
})
})
}catch (err) {
console.log("err : " + err)
}
I am currently setting up push notifications on my react/firebase project.
I have followed all the steps and added the firebase-messaging-sw.js, getToken etc..
I used to be able to get a FCM token back from getToken but I am no longer able to do so due to this error message:
An error occurred while retrieving token. FirebaseError: Messaging:
A problem occurred while subscribing the user to FCM: Request contains an invalid argument.
(messaging/token-subscribe-failed).
at requestGetToken (requests.ts:67:1)
at async getNewToken (token-manager.ts:139:1)
This error occurs when I call the getTokenFound() method
Before when this was working, I would also have problems with the service worker if I was running the same project on a different system. Only my main development system was able to not hit the service worker error:
An error occurred while retrieving token. FirebaseError: Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker for scope
('http://localhost:3000/firebase-cloud-messaging-push-scope%27) with script
('http://localhost:3000/firebase-messaging-sw.js%27): ServiceWorker script evaluation failed
(messaging/failed-service-worker-registration).
Two two issues seem to be persistent, often it seems like an error loop happens if I deny the notification permissions and then try to allow them again, I would get the invalid argument error.
Here are my relevant code blocks below, I'm really not sure what else to change here. The react setup for push notifications seems very inconsistent depending on what machine Im on. Many thanks for any insight!
firebase-messaging-sw.js (in public dir with index.html)
importScripts('https://www.gstatic.com/firebasejs/8.3.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.3.1/firebase-messaging.js');
const firebaseConfig = {
apiKey: DATA,
authDomain: DATA,
databaseURL: DATA,
projectId: DATA,
storageBucket: DATA,
messagingSenderId: DATA,
appId: DATA,
measurementId: DATA
};
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
messaging.onBackgroundMessage(function (payload) {
console.log("Received background message ", payload);
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
icon: "../src/assets/image/default.svg",
tag: "notification-1"
};
return self.registration.showNotification(
notificationTitle,
notificationOptions
);
});
firebase.js
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getFunctions } from "firebase/functions";
import { getStorage } from "firebase/storage";
import { getMessaging, getToken, onMessage } from "firebase/messaging";
import 'firebase/storage';
export const app = initializeApp({
apiKey: data,
authDomain: data,
databaseURL: data,
projectId: data,
storageBucket: data,
messagingSenderId: data,
appId: data,
measurementId: data
});
export const messaging = getMessaging(app);
export const firestore = getFirestore(app);
export const functions = getFunctions(app);
export const storage = getStorage(app);
export const getTokenFound = async () => {
let currentToken = "";
try {
currentToken = await getToken(messaging, { vapidKey: myVapidKey});
if (currentToken) {
console.log("CURRENT TOKEN", currentToken)
} else {
}
} catch (error) {
console.log("An error occurred while retrieving token. ", error);
}
return currentToken;
};
export const onMessageListener = () =>
new Promise((resolve) => {
onMessage(messaging, (payload) => {
console.log("payload", payload)
resolve(payload);
});
});
the data loading good, but when I keep the page for half hour without any actions and then trying to load data without refreshing page - I'm getting this error. I've found similar issue here and added firebase.firestore().enablePersistence(). It didn't help. The other weird observation, even when the data loading successfully I'm often observe in network this error
My firebase config:
import firebase from "firebase";
const config = {
apiKey: "AIzaSyC**********1vY38Q",
authDomain: "****.firebaseapp.com",
databaseURL: "https://********",
projectId: "myproject",
storageBucket: "****.appspot.com",
messagingSenderId: "209382989",
appId: "1:1**********ceda27",
measurementId: "G*****B96",
};
firebase.initializeApp(config);
firebase.firestore().enablePersistence();
export const db = firebase.firestore();
export default firebase;
My request:
import firebase, { db } from "./firebase.config";
const getData = async (db, collection, docId) => {
const data = await db.collection(collection).doc(docId.toString()).get();
return { data: data.data()?.history.map((con) => ({ ...con, profileId: docId, names: {} })) || [], docId };
};
export const getCollectionData = async (collection, docIdArray) => {
try {
await firebase.auth().signInAnonymously();
return new Promise((resolve, reject) => {
console.log("in promise");
firebase.auth().onAuthStateChanged(async (user) => {
if (user) {
try {
const data = await Promise.all((docIdArray.map((docId) => getData(db, collection, docId))));
resolve(data);
} catch (error) {
reject(error);
}
} else {
console.log("user is signed out");
// User is signed out
// ...
}
});
});
} catch (error) {
console.log.apply(error);
}
};
after page reloading it works fine. 403 error sometimes dissappeared sometimes not. Does anybody faced something similar?
I am following the react native firebase docs (https://rnfirebase.io/docs/v5.x.x/auth/phone-auth) on Phone Authorization and am confused about the need (or no need) for reCAPTCHA.
The docs do not pass a second parameter to the signInWithPhoneNumber() method but when calling the method I receive an error asking for the recaptchaVerifier as the second parameter. Because I am writing the app for both iOs and Android I utilized the Web connection to Firebase and am not using the generated JSON file. I believe this is my issue as it thinks I am calling the API from a non-mobile device.
Is Firebase Web the best way to connect a React Native cross platform application? If it is, is there a way to generate the reCAPTCHA code?
The firebase docs talk about an invisible reCAPTCHA but they only provide code for HTML with a button ID and whatnot. (I did try to give and an ID as a prop but found no success) https://firebase.google.com/docs/auth/web/phone-auth
My config file:
import firebase from 'firebase';
class Config {
constructor() {
if (!firebase.apps.length) {
firebase.initializeApp({
apiKey: "AIaskdjf93rlaksdjf99999",
authDomain: "myDomain.firebaseapp.com",
databaseURL: "https://myDomain.firebaseio.com",
projectId: "myDomain",
storageBucket: "",
messagingSenderId: "88827277272",
appId: "somenumbersomitted",
measurementId: "akjdsfkljad"
});
}
}
login = async (user, success_callback, failed_callback) => {
await firebase
.auth()
.signInWithEmailAndPassword(user.userName, user.password)
.then(success_callback, failed_callback);
};
//todo:: need to update signInWithPhoneNumber second param to be the recaptcha token
loginWithPhone = async (phoneNumber, success_callback, failed_callback) => {
var applicationVerifier = ?????;
await firebase
.auth()
.signInWithPhoneNumber(phoneNumber, applicationVerifier)
.then(success_callback, failed_callback);
};
//todo: figure out how to get this method to work in RN. Not able to take in button ID...
recaptchaVerifier = async (phoneNumber, success_callback, failed_callback) =>{
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
'size': 'invisible',
'callback': function(response) {
loginWithPhone(phoneNumber, success_callback, failed_callback);
}
});
};
}
const config = new Config();
export default config;
I managed to get phone number authentication working on React Native by using https://rnfirebase.io/ and the following code:
const sendSmsCode = async (phoneNumber: string) => {
const isUserPhoneNumberLinked = await getIsUserPhoneNumberLinked(
phoneNumber
);
if (!isUserPhoneNumberLinked) {
} else {
try {
let confirmationResult = await firebase
.auth()
.signInWithPhoneNumber(phoneNumber, true);
Promise.resolve();
setIsSmsCodeSent(true);
confirmationRef.current = confirmationResult;
} catch (error) {
throw error;
}
}
};
And then you can use confirmationRef.current.confirm() to confirm the sms code:
const verifySmsCode = async () => {
const result = await confirmationRef.current.confirm(smsCode);
if (result.user) {
dispatch(authenticatedUserAction());
}
};
I am using firebase messaging for web push notification with react. But browser show this message
Messaging: This browser doesn't support the API's required to use the firebase SDK. (messaging/unsupported-browser)
This is code :
const initializedFirebaseApp = firebase.initializeApp({
apiKey: "XXXXXX",
authDomain: "XXXXXXX",
databaseURL: "XXXXXXXXX",
projectId: "XXXXXX",
storageBucket: "XXXX",
messagingSenderId: "XXXXXX",
appId: "XXXXXX"
});
if (firebase.messaging.isSupported()) {
let messaging = initializedFirebaseApp.messaging();
}
firebase.messaging.isSupported() is always returning the false. Is there any way I should proceed?
Version for react : 16.8.2 and firebase version : 6.0.2
FCM supports only in localhost and the https enabled sites only. if you want FCM to support you need to either work on localhost or deploy somewhere (you can use firebase).
If you are using proxy using nginx like local.somehost.com cloud messaging doesn't support. To solve this you need to make your local.somehost.com as HTTPS you can install openssl and certificate and key in your nginx.
I think this solves your problem.
In addition to the above explanation you can check if the browser supports messaging by doing:
const messaging = firebase.messaging.isSupported() ? firebase.messaging() : null
isSupported() in version 9
return Promise so you should wait for resolving
const messaging = (async () => {
try {
const isSupportedBrowser = await isSupported();
if (isSupportedBrowser) {
return getMessaging(config);
}
console.log('Firebase not supported this browser');
return null;
} catch (err) {
console.log(err);
return null;
}
})();
If you are using version 9 you should pass messaging to (onMessageListener resolver and getToken )
onMessageListener
export const onMessageListener = async () =>
new Promise((resolve) =>
(async () => {
const messagingResolve = await messaging;
onMessage(messagingResolve, (payload) => {
// console.log('On message: ', messaging, payload);
resolve(payload);
});
})()
);
getToken
export const requestForToken = async (dispatch) => {
try {
const messagingResolve = await messaging;
const currentToken = await getToken(messagingResolve, {
vapidKey: *your FCM APP SERVER KEY*,
});
if (currentToken) {
*your code*
}
} catch (err) {
console.log('An error occurred while retrieving token. ', err);
}
};
I used dynamic imports for solving this issue so that the file is not even evaluated before the feature is detected. I am using firebase SDK 8.2.0.
This is how my useEffect function looks like on the top level of my app.
import { isSupported } from "firebase/messaging";
useEffect(() => {
(async () => {
const hasFirebaseMessagingSupport = await isSupported();
if (hasFirebaseMessagingSupport) {
const { requestForToken } = await import("./api/cloud-notification/firebase");
await requestForToken();
}
})();
}, []);
This is how my firebase connection file looks like ("./api/cloud-notification/firebase"):
import { initializeApp } from "firebase/app";
import { getMessaging, getToken } from "firebase/messaging";
const FIREBASE_VAPID_KEY = "your-firebase-public-vapid-key";
const firebaseConfig = {
apiKey: 'api-key',
authDomain: 'project-id.firebaseapp.com',
projectId: 'project-id',
storageBucket: 'project-id.appspot.com',
messagingSenderId: 'sender-id',
appId: 'app-id',
measurementId: 'G-measurement-id',
};
initializeApp(firebaseConfig);
const messaging = getMessaging();
const getFirebaseToken = async () => {
try {
const currentToken = await getToken(messaging, { vapidKey: FIREBASE_VAPID_KEY });
if (!currentToken) {
console.log("No registration token available. Request permission to generate one.");
}
} catch (error) {
console.log("An error occurred while retrieving token. ", error);
}
};
export const requestForToken = async () => {
try {
const permission = await Notification.requestPermission();
if (permission === "granted") {
await getFirebaseToken();
}
} catch (error) {
console.log("An error occurred while getting user permission. ", error);
}
};