Firebase authentication not working in NuxtJs application - firebase

In am using Firebase Authentication in my Nuxt App. I am following the Firebase Documentation for setting up Authentication using GoogleAuthProvider. In my case, onAuthStateChanged() listener returns null even after successfull redirect.
When the user enter my web application, Nuxt will execute the plugin in the client side. There the firebase configuration is initialized. Then the initUser() function defined in useFirebaseAuth.ts composable is called. If user successfully logged In, log the user details.
Note : After I encountered this error, I replaced signInWithRedirect to signInWithPopup, it works very well.
// plugins/firebase.client.ts
import { initializeApp } from "firebase/app";
import { initUser } from "~~/composables/useFirebaseAuth";
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig();
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
appId: "...",
messagingSenderId: "...",
};
// Initialize Firebase
const firebaseApp = initializeApp(firebaseConfig);
initUser(firebaseApp);
})
// composables/useFirebaseAuth.ts
import { FirebaseApp } from "firebase/app";
import { getAuth,signInWithPopup, GoogleAuthProvider, onAuthStateChanged, signInWithRedirect, signOut, User } from "firebase/auth";
import { equalTo, getDatabase, onValue, orderByChild, query, ref as dbRef } from "firebase/database";
export const signInUser = async () => {
const provider = new GoogleAuthProvider();
const auth = getAuth();
await signInWithRedirect(auth, provider)
}
export const initUser = async (firebaseApp: FirebaseApp) => {
const auth = getAuth(firebaseApp)
const db = getDatabase()
onAuthStateChanged(auth, user => {
if (user) {
console.log(user)
} else {
console.log("user not logged in"
return navigateTo('/login')
}
});
}
export const signOutUser = async () => {
const auth = getAuth();
await signOut(auth)
}
In the above code, I always get the user value as null. I am working on the project for 2 months. The authentication works fine almost one month ago. But it is not working now. Please help me to resolve the issue.
# node --version
v19.5.0
# npm version
{
npm: '9.3.1',
node: '19.5.0',
v8: '10.8.168.25-node.11',
uv: '1.44.2',
zlib: '1.2.13',
brotli: '1.0.9',
ares: '1.18.1',
modules: '111',
nghttp2: '1.51.0',
napi: '8',
llhttp: '8.1.0',
uvwasi: '0.0.14',
acorn: '8.8.1',
simdutf: '3.1.0',
undici: '5.14.0',
openssl: '3.0.7+quic',
cldr: '42.0',
icu: '72.1',
tz: '2022g',
unicode: '15.0',
ngtcp2: '0.8.1',
nghttp3: '0.7.0'
}
I have gone through many answers posted for same question in the stackoverflow website. But those answers didn't solved my issues.

Related

Can we make firebase actions serializable for redux toolkit?

I am using react and redux toolkit in a project. I also use firebase to manage authentication for this project.
I'm dispatching an async thunk that I call login to login users. And here I am calling the signInWithEmailAndPassword method of firebase. I export this method from a file named firebase.ts. You can find code snippets below.
// firebase.ts
import { initializeApp } from "firebase/app";
import {
getAuth,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
sendPasswordResetEmail,
sendEmailVerification,
updateEmail,
updatePassword,
reauthenticateWithCredential,
EmailAuthProvider,
} from "firebase/auth";
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,
measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID,
};
const firebaseApp = initializeApp(firebaseConfig);
export const auth = getAuth(firebaseApp);
export {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
sendPasswordResetEmail,
sendEmailVerification,
updateEmail,
updatePassword,
reauthenticateWithCredential,
EmailAuthProvider,
};
// UserContent/thunks.ts
import { createAsyncThunk } from "#reduxjs/toolkit";
import { auth, signInWithEmailAndPassword, signOut } from "#app/api/firebase";
import { UserLoginForm } from "#common/formTypes";
export const login = createAsyncThunk(
"userContent/login",
async (data: UserLoginForm) => {
const { email, password } = data;
const response = await signInWithEmailAndPassword(auth, email, password);
return response;
}
);
export const logout = createAsyncThunk("userContent/logout", async () => {
const response = await signOut(auth);
return response;
});
But as you can guess in the console, I get a warning like the following.
Console Warning Image
Of course I know I can turn off this warning very easily. But is there a better way to solve this?
You can convert your response to a serializable object by adding .toJson() to the response.
export const login = createAsyncThunk(
"userContent/login",
async (data: UserLoginForm) => {
const { email, password } = data;
const response = await signInWithEmailAndPassword(auth, email, password);
return response.toJSON();
}
);

"Firebase Error : Firestore has already been started and its settings can no longer be changed." connecting Firebase v9 with Firestore Emulator

I have updated to Firebase v9 a few weeks ago and I have an issue when trying to connect my Firebase App to Firestore Emulator.
firebase.js (my VueJS plugin, where I setup Firebase) :
import { initializeApp, getApps } from "firebase/app"
import { getAuth, connectAuthEmulator, onAuthStateChanged } from "firebase/auth";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore"
import { getStorage, connectStorageEmulator } from "firebase/storage";
import { getFunctions, connectFunctionsEmulator } from 'firebase/functions';
import { isSupported, getAnalytics } from "firebase/analytics";
export default async ({ app }, inject) => {
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_SERVICE_ID,
appId: process.env.FIREBASE_APP_ID,
measurementId: process.env.FIREBASE_MEASUREMENT_ID,
}
// I've checked, the values of firebaseConfig are all set here.
// This IF statement is here to avoid initializing the app several times
const apps = getApps();
let firebaseApp = null;
if (!apps.length) {
firebaseApp = initializeApp(firebaseConfig);
}
else {
firebaseApp = apps[0];
}
// INIT AUTH
const auth = getAuth();
auth.languageCode = 'fr';
onAuthStateChanged(auth, async authUser => {
const claims = authUser ? (await authUser.getIdTokenResult(true)).claims : null;
await app.store.dispatch('onAuthStateChanged', { authUser, claims });
},
(error) => {
console.error("Firebase Auth onAuthStateChanged ERROR", error)
});
// Get other services
const firestore = getFirestore(firebaseApp);
const storage = getStorage(firebaseApp);
const functions = getFunctions(firebaseApp, process.env.FIREBASE_REGION);
// Setup analytics if supported
let analytics = null;
const analyticsSupported = await isSupported()
if (analyticsSupported) {
analytics = getAnalytics();
analytics.automaticDataCollectionEnabled = false;
}
// Connecting to emulators
if (process.client && process.env.APP_ENV === 'local') {
console.log("LOCAL ENVIRONMENT, CONNECTING TO EMULATORS...");
connectAuthEmulator(auth, "http://localhost:9099");
connectFirestoreEmulator(firestore, 'localhost', 8080);
connectStorageEmulator(storage, "localhost", 9199);
connectFunctionsEmulator(functions, "localhost", 5001);
}
Inject firebase objects into my VueJS app
const fire = { auth, firestore, storage, functions, analytics }
inject('fire', fire);
}
Here is the error I get, caused by this line : connectFirestoreEmulator(firestore, 'localhost', 8080);
FirebaseError Firestore has already been started and its settings can
no longer be changed. You can only modify settings before calling any
other methods on a Firestore object.
I am not trying to modify Firestore object's settings property myself, so it has to be the method connectFirestoreEmulator.
The problem can be narrowed down to the following code :
import { initializeApp } from "firebase/app"
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore"
export default async ({ app }, inject) => {
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_SERVICE_ID,
appId: process.env.FIREBASE_APP_ID,
measurementId: process.env.FIREBASE_MEASUREMENT_ID,
}
firebaseApp = initializeApp(firebaseConfig);
const firestore = getFirestore(firebaseApp);
if (process.env.APP_ENV === 'local') {
connectFirestoreEmulator(firestore, 'localhost', 8080);
}
const fire = { auth, firestore, storage, functions, analytics };
inject('fire', fire);
}
I've managed to avoid triggering the error by adding process.client so it doesn't connect to emulators on server-side (SSR) :
if (process.client && process.env.APP_ENV === 'local') {
However when I add that, the emulators are not connected when code is executed server-side (SSR) on the first page load, and initial Firestore data is being read from the real Firebase App instead of the emulators.
Any idea what can be done to manage proper connection to Firestore emulator on SSR ?
Is this a Firebase bug ?
Versions I use :
In my App : Firebase JS SDK v9.6.9
Emulators : firebase-tools v10.4.0 for the emulators
What I've already read/tried :
https://firebase.google.com/docs/reference/js/app.md#initializeapp
Firebase Firestore emulator error `Host has been set in both settings() and useEmulator(), emulator host will be used`
FirebaseFirestore has already been started and its settings can no longer be changed
It's been a while, but I ran into a similar issue, and after a lot of hairpulling, I ended up with a solution (though it feels a little hacky).
Before running the connectFirestoreEmulator line, check if firestor._settingsFrozen is false. So you only run that line basically if Firestore hasn't already been initialized. You can check that firestore is getting initialized with the emulator settings by logging out the firestore variable before the connectFirestoreEmulator line and seeing what the settings say there--if it says port is 8080 and host is localhost, then you're good.
Here's my code for comparison (slightly different setup from yours but I believe we were running into the same issue):
import { initializeApp } from 'firebase/app';
import { connectAuthEmulator, getAuth } from 'firebase/auth';
import { connectFirestoreEmulator, getFirestore } from 'firebase/firestore';
const firebaseConfig = {
apiKey: "XXXXXXXXX",
authDomain: "XXXXXXXXX",
projectId: "XXXXXXXXX",
storageBucket: "XXXXXXXXX",
messagingSenderId: "XXXXXXXXX",
appId: "XXXXXXXXX",
measurementId: "XXXXXXXXX",
};
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const db = getFirestore(app);
export default (context) => {
if (context.env.appEnv === 'dev') {
connectAuthEmulator(auth, `http://127.0.0.1:${context.env.authPort}`);
if (!db._settingsFrozen) {
connectFirestoreEmulator(db, '127.0.0.1', parseInt(context.env.firestorePort));
}
}
}
Reviewing Firebase JS SDK issues related, it seems that the issue is because the Firestore instance (which is initialized like this: firestore = getFirestore(firebaseApp)) is called after the emulator (connectFirestoreEmulator) has been started.
After calling the "connectFirestoreEmulator" method, "firestore" variable is being used in the constant variable "fire = { auth, firestore, storage, functions, analytics }"
If you use "const fire" before connecting to the emulator, the problem may be solved.
Here is a code example that might help you:
firebaseApp = initializeApp(firebaseConfig);
const fire = { auth, firestore, storage, functions, analytics };
const firestore = getFirestore(firebaseApp);
if (process.env.APP_ENV === 'local') {
connectFirestoreEmulator(firestore, 'localhost', 8080);
}
As a reference, I used this github repository.
You can try checking the setting.host value of your firebase object in order to check if it is already 'localhost', so you can skip calling the connectFirestoreEmulator() function.
This did happen to me in an Angular application using Hot Module Replacement. I tried to use a global constant, but did not work.
In my case, I'm using AngularFire (https://github.com/angular/angularfire), so I had to do something like this:
// ...
const firestore = getFirestore();
const host = (firestore.toJSON() as { settings?: { host?: string } }).settings?.host ?? '';
// console.log({ host });
if (process.env.APP_ENV === 'local' && !host.startsWith('localhost')) {
connectFirestoreEmulator(firestore, 'localhost', 8080);
}
// ...
In my case I had to use firestore.toJSON() in order to access the settings property, check how it is in your case.

firebaseConfig.default.auth promise rejection error

I am trying to signup user with facebook but i am seeing very rigid error and it seems there is no solved help out there so i am asking again
thats my code
async function signInWithFacebook() {
// const appId = Expo.Constants.manifest.extra.facebook.appId;
Facebook.initializeAsync(appid)
const permissions = ['public_profile']; // Permissions required, consult Facebook docs
const {
type,
token,
} = await Facebook.logInWithReadPermissionsAsync(
{permissions}
);
if(type == "success"){
const credential = initFirebase.auth.FacebookAuthProvider.credential(token);
initFirebase.auth().signInWithCredential(credential)
.catch(err => {
console.log(err)
})
}
}
i am using appid in strings but i have not added it here hope you understand that.
and the error is this
this is my firebase config file code
import firebase from "firebase/app"
import "firebase/firestore"
import "firebase/auth"
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "xxxxxxxx",
authDomain: "xxxxxx",
databaseURL: "xxxxxx",
projectId: "xxxx",
storageBucket: "xxxxx",
messagingSenderId: "xxxxx",
appId: "xxxxx"
};
// Initialize Firebase
const initFirebase = firebase.initializeApp(firebaseConfig);
export default initFirebase
variable values are hidden because of privacy .i worked with firestore and that worked but i am seeing issue with auth with facebook .
i am using react native , firebase , expo and not firebase sdk
You don't have to register a Facebook App for Login with Facebook using Firebase. You can use the below code with Firebase Facebook Authentication enabled in the console.
export const loginWithFacebook = (accessToken) => {
const credential = initFirebase.auth.FacebookAuthProvider.credential(accessToken);
return new Promise((resolve, _reject) => {
signInWithCredential(credential).then(response => {
resolve(response);
});
});
};

bundling failed: SyntaxError: Unexpected end of JSON input in react native

i am using firebase in my react native project. when i am try to sign up user with email and password this error is comming.
i am using window OS and only andorid render
Note: i had read all questions related to this but nothing helped
newbiew to react native .please guide in proper way
package.json
"firebase": "^5.8.2",
"native-base": "^2.11.0",
"react": "16.6.3",
"react-native": "^0.57.8",
"react-native-elements": "^0.19.1",
"react-native-firebase": "^5.2.2",
"react-native-gesture-handler": "^1.0.15",
"react-native-maps": "^0.23.0",
"react-native-svg": "^8.0.10",
"react-native-vector-icons": "^6.2.0",
"react-navigation": "^3.2.1"
Code for sign up
import * as firebase from 'firebase'
//Intiazlize firebase
const firebaseConfig = {
apiKey: "AIzaSyCUK5QkcvTcvfCKlbwnnI8GskIgcLGMcqA",
authDomain: "trailertracker-da09c.firebaseapp.com",
databaseURL: "https://trailertracker-da09c.firebaseio.com",
projectId: "trailertracker-da09c",
storageBucket: "",
}
firebase.initializeApp(firebaseConfig)
signUpUser = (email,password) => {
try{
if(this.state.password.length < 6 ){
alert("Please Enter Valid Email and Password")
return
}
firebase.auth().createUserWithEmailAndPassword(email,password)
} catch(err){
console.log(err)
}
}
Complete error is
Loading dependency graph, done. error: bundling failed: SyntaxError:
Unexpected end of JSON input
at JSON.parse ()
at FileStore.get (F:\React Native\ReactProjects\trailer-tracker\TrailerTracker\node_modules\metro-cache\src\stores\FileStore.js:26:19)
at F:\React Native\ReactProjects\trailer-tracker\TrailerTracker\node_modules\metro-cache\src\Cache.js:76:40
at Generator.next ()
at step (F:\React Native\ReactProjects\trailer-tracker\TrailerTracker\node_modules\metro-cache\src\Cache.js:18:30)
at F:\React Native\ReactProjects\trailer-tracker\TrailerTracker\node_modules\metro-cache\src\Cache.js:37:14
at new Promise ()
at F:\React Native\ReactProjects\trailer-tracker\TrailerTracker\node_modules\metro-cache\src\Cache.js:15:12
at Cache.get (F:\React Native\ReactProjects\trailer-tracker\TrailerTracker\node_modules\metro-cache\src\Cache.js:102:7)
at F:\React Native\ReactProjects\trailer-tracker\TrailerTracker\node_modules\metro\src\DeltaBundler\Transformer.js:166:34
BUNDLE [android, dev] ....../index.js 68.2% (947/1147), failed.
is this another error or error in firebase ?
Help will be highly appreciated
Thanks
To get started with firebase in react native.
add firebase dependency
yarn add firebase
Goto Firebase and make a new project and going to the section
Add Firebase to your web app
Make a class for configation of Firebase like this
import firebase from "#firebase/app";
require("firebase/database");
require("firebase/storage");
require("firebase/auth");
let config = {
apiKey: "YOUR PROJECT apiKey",
authDomain: "YOUR PROJECT authDomain",
databaseURL: "YOUR PROJECT databaseURL",
projectId: "XXXXXXXX",
storageBucket: "",
messagingSenderId: "XXXXXXXXXX",
appId: "XXXXXXXXXXXXXXXXXXXXXXXX"
};
export default class DBHandler {
static auth;
static database;
static init() {
firebase.initializeApp(config);
DBHandler.database = firebase.database();
DBHandler.auth = firebase.auth();
}
}
in App.js initialize Firebase
import DBHanlder from "./src/api/constants";
export default class App extends Component {
componentDidMount = () => {
DBHanlder.init();
};
render() {
return <YourApp />;
}
}
Your're done with initialization part .now you can use for auth like below
import DBHandler from "../api/constants";
class Login extends Component {
signinUser = () => {
DBHandler.auth.signInWithEmailAndPassword(email, password)
.then(() => {
//Do what you want
})
.catch((error) => {
//handle error
var errorCode = error.code;
var errorMessage = error.message;
alert(errorMessage);
console.log("ERROR");
console.log(errorCode, errorMessage);
});
}
}}

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