Firebase Configuration not working in VueJs - firebase

I am trying to use firebase in an app. However, I am trying to render routes based on user authentication status but for some reason, firebase tells me the user is logged in but the user isn't. Here is my store/index.js file. I am using vuex.
getRoutes (state) {
let mRoutes = []
firebase.auth().onAuthStateChanged(function (User) {
if (User) {
console.log('Not loggedin')
mRoutes = state.authenticatedUserRoutes
} else {
console.log('Loggedin' + mRoutes)
mRoutes = state.unAuthenticatedUserRoutes
}
})
return mRoutes
}
I have already initiated firebase inthe main.js file as shown below
import * as firebase from 'firebase'
import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import router from './router'
import store from './store'
import vuetify from './plugins/vuetify'
Vue.config.productionTip = false
new Vue({
router,
store,
vuetify,
created () {
firebase.initializeApp({
apiKey: '#################',
authDomain: '######################',
databaseURL: '######################',
projectId: '######################',
storageBucket: '######################',
messagingSenderId: '######################',
appId: '######################',
measurementId: 'G-SEPRYKF81S'
})
},
render: h => h(App)
}).$mount('#app')

Seems like this could be because you're using onAuthStateChanged which is an observer that fires when the auth state changes.
https://firebase.google.com/docs/reference/js/firebase.auth.Auth#on-auth-state-changed
Adds an observer for changes to the user's sign-in state.
Prior to 4.0.0, this triggered the observer when users were signed in, signed out, or when the user's ID token changed in situations such as token expiry or password change. After 4.0.0, the observer is only triggered on sign-in or sign-out.
you should probably check the state manually first.

Related

Firebase App named '[DEFAULT]' already exists with different options or config

I'm building an app with NextJS, NextAuth and Firebase.
While implementing NextAuth, I've encountered this error:
error - FirebaseError: Firebase: Firebase App named '[DEFAULT]' already exists with different options or config (app/duplicate-app).
Here's my code:
[...NextAuth].js
import NextAuth from "next-auth/next";
import GoogleProvider from "next-auth/providers/google";
import { FirestoreAdapter } from "#next-auth/firebase-adapter";
import { db } from "#/firebase/config";
export default NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
}),
],
adapter: FirestoreAdapter(db),
});
My firebase config file
import { initializeApp, getApp, getApps } from "firebase/app";
import "firebase/auth";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
apiKey: ___,
authDomain: ___,
projectId: ___,
storageBucket: ___,
messagingSenderId: ___,
appId: ___,
measurementId: ___,
};
const app =
getApps().length === 0
? initializeApp({ ...firebaseConfig, projectId: firebaseConfig?.projectId })
: getApp();
const db = getFirestore(app);
export { app, db };
As you can see in my config file, I'm testing if an app already exists, but it doesn't seem to work.
I've checked if somebody already had the same problem as me, but I didn't find an answer.
Any idea?
Thanks a lot,
Gabriel
According to the documentation for the Firebase Adapter for NextAuth.js, you should be passing in the configuration object to the adapter directly or an instance of Firestore from the Admin SDK (i.e. using import { getFirestore } from "firebase-admin/firestore").
Initially, you should try removing your "#/firebase/config" import and just use the configuration directly.
import NextAuth from "next-auth/next";
import GoogleProvider from "next-auth/providers/google";
import { FirestoreAdapter } from "#next-auth/firebase-adapter";
const firebaseConfig = {
apiKey: ___,
authDomain: ___,
projectId: ___,
storageBucket: ___,
messagingSenderId: ___,
appId: ___,
measurementId: ___,
};
export default NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
}),
],
adapter: FirestoreAdapter(firebaseConfig),
});
This initialization behaviour is defined in the main constructor in src/index.ts and in the initialization utility method in src/utils.ts.
The next step to try would be to make sure your Next.js sources make use of the Firebase Admin SDK instead of the client-side Firebase SDK which behaves differently.
If the above doesn't work, you can look for the more general cause. Sift through your codebase and look for statements that initialize Firebase service providers before your code pulls in "#/firebase/config". Any call to getApp() without any arguments will silently initialize the default FirebaseApp instance.
// NOTE: this is pseudo-code, not the actual implementation
// gets the named/default app, throwing an error if not initialized
export function getApp(name: string = DEFAULT_ENTRY_NAME): FirebaseApp {
const app = _apps.get(name);
if (!app && name === DEFAULT_ENTRY_NAME) return initializeApp(); // <-- this initializeApp is your problem
if (!app) throw new Error(name + " not initialized");
return app;
}
This also applies to calls that initialize a service (e.g. getFirestore()) without any app argument as they also will call getApp() internally.
// NOTE: this is pseudo-code, not the actual implementation
export function getFirestore(app?: FirebaseApp) {
app = app || getApp(); // use given app or use default
return app._providers.get('firestore') || initializeFirestore(app, DEFAULT_SETTINGS)
}
Unfortunately, tracking down this particular problem can be a pain as you module bundler/build tool might be "tree-shaking" the code and stripping what it thinks is unnecessary - which may include your getApp() and getFirestore() calls if you don't use app or db in the local code. Using just import "#/firebase/config" in this case should solve that.

How to retrieve auth cookie on serverInit in Pinia store?

I have recently started learning Nuxt 3 by trying to implement basic user auth logic with firebase and now I would need to retrieve the cookie from the req to initialise the user auth state inside Pinia store but it seems like nuxtServerInit is not supported by Pinia. After realising this I proceeded to a different solution where I'm using server middleware to pass the req object to an action called nuxtServerInit() but then I ran into another problem which is that I cannot call the auth().verifyIdToken(token) from there because the firebase is initialised inside a plugin which runs afterwards.
After this I also tried to initialise firebase inside server middleware and pass auth object to nuxtServerInit() action and set it to the state but then I could not call an action from there I guess because Pinia has not initialised yet?
How could I overcome the original problem? What could be a better approach?
Heres the firebase init plugin:
import { initializeApp } from 'firebase/app'
import { getAuth } from "firebase/auth"
import { getFirestore } from 'firebase/firestore'
import { useStore } from '~/store/index.js'
export default defineNuxtPlugin(nuxtApp => {
const firebaseConfig = {
apiKey: "API_KEY",
authDomain: "AUTH_DOMAIN",
projectId: "PROJECT_ID",
storageBucket: "STORAGE_BUCKET",
messagingSenderId: "MESSAGING_SENDER_ID",
appId: "APP_ID"
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app)
const firestore = getFirestore(app)
nuxtApp.vueApp.provide('auth', auth)
nuxtApp.provide('auth', auth)
nuxtApp.vueApp.provide('firestore', firestore)
nuxtApp.provide('firestore', firestore)
const store = useStore()
console.log('AUTH', auth)
auth.onAuthStateChanged((user) => {
store.setAuth(user)
})
})

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

Setting up firebase with react native

I am having difficulties setting up firebase with react native.
src/components/firebase.js
import firebase from '#firebase/app';
import '#firebase/auth';
const firebaseConfig = {
apiKey: "AIzaSyCJshsr47p3IriQGF0V4gaVd-bCuo_HN6A",
authDomain: "auth-8f2ec.firebaseapp.com",
databaseURL: "https://auth-8f2ec.firebaseio.com",
projectId: "auth-8f2ec",
storageBucket: "auth-8f2ec.appspot.com",
messagingSenderId: "1013084520551"
};
const Firebase = firebase.initializeApp(firebaseConfig);
export default Firebase;
src/components/LoginForm.js
First I import Firebase
import Firebase from './firebase';
then authentication is done this way.
Firebase.auth().signInWithEmailAndPassword(email, password)
.then(this.onLoginSuccess.bind(this))
.catch(() => {
Firebase.auth().createUserWithEmailAndPassword(email, password)
.then(this.onLoginSuccess.bind(this))
.catch(this.onLoginFail.bind(this));
});
};
src/App.js
Firebase is imported in this way
import Firebase from './components/firebase';
The component will mount method runs this way.
componentWillMount(){
Firebase.auth().onAuthStateChanged((user) => {
console.log(Firebase.auth());
if(user){
console.log('firebase login success');
this.setState({ loggedIn: true});
}
else{
console.log('firebase login failed');
this.setState({ loggedIn: false });
}
});
};
The result is a spinner. Something is wrong with the way firebase is being imported.
Help would be appreciated. Thanks in advance.
Thanks in advance.
Strange you're importing with "#" at the beginning. Try to import this way:
import * as firebase from 'firebase/app';
import 'firebase/auth';

React Native Firebase Auth function

I'm using react native crud application with using firebase real time storage. I use firebase auth functionality with email and password logging. but my firebase auth is not working. It gets more issues with firebase connection. I used this function to connect firebase.
componentWillMount() {
firebase.initializeApp({
apiKey: 'xxxxxxxxxxxxxxxxxxxxxxxx',
authDomain: 'xxxxxxxxxxxxxxxxxxxxxx',
databaseURL: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx',
projectId: 'xxxxxxxxxxxxxxxxxxxxx',
storageBucket: 'xxxxxxxxxxxxxxxxxxxxxxxx',
messagingSenderId: 'xxxxxxxxxxxxxxx'
});
}
My log in button auth functionality is looks like this one:
state = { email: '', password: '', error: '' };
onButtonPress() {
const { email, password } = this.state;
firebase.auth().signInWithEmailAndPassword(email, password)
.catch(() => {
firebase.auth().createUserWithEmailAndPassword(email, password)
.catch(() => {
this.setState({ error: 'Authenticaton Failed.' });
});
});
}
I import firebase libraries like this:
import * as firebase from 'firebase';
import 'firebase/firestore';
import 'firebase/auth';
But this configurations are not working. It shows me this error:
undefined is not a function (evaluating 'firebase.auth()')
I used to get text input values this method:
value={this.state.password}
onChangeText={password => this.setState({ password })}
your firebase config only exists in your componentDidMount. Try like this:
Create a file <namefile>.js wherever you want and add:
import * as firebase from 'firebase'
import 'firebase/auth';
const config = {
apiKey: "your key",
authDomain: "domain",
databaseURL: xxxx",
projectId: "xxxx",
storageBucket: "xxx",
messagingSenderId: "xxxx"
};
if (!firebase.apps.length) {
firebase.initializeApp(config);
}
const auth = firebase.auth();
export {
auth
};
import auth in your component and in your button method change your code by:
auth.signInWithEmailAndPassword
it should work and every time you need to use auth, you just need to import it

Resources