I am having issues implementing firebase authentication with Google Provider in NextJS. I set up the environment variables and am successfully connecting to firebase. I am receiving the following error and cant seem to figure out a solution, TypeError: Cannot read properties of undefined (reading 'GoogleAuthProvider'). Below is my code.
//firebaseApp.js
import { initializeApp, getApps } from "firebase/app"
import { getFirestore } from "firebase/firestore"
import { getAuth } from "firebase/auth"
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};
if (getApps().length === 0) {
console.log('Error Connecting to Firebase')
}
const app = initializeApp(firebaseConfig)
const db = getFirestore(app)
const auth = getAuth(app)
export { db, auth }
//firebaseAuthUI.config.js
export const uiConfig = (firebase) => {
return {
signInFlow: "popup",
signInSuccessUrl: "/",
signInOptions: [firebase.auth.GoogleAuthProvider.PROVIDER_ID],
};
};
//login.js
import Head from 'next/head';
import { useRouter } from 'next/router';
import { useAuthState } from 'react-firebase-hooks/auth';
import StyledFirebaseAuth from 'react-firebaseui/StyledFirebaseAuth';
import { auth, firebase } from '../app/firebaseApp';
import { uiConfig } from '../config/firebaseAuthUI.config';
export default function Login() {
const [user, loading, error] = useAuthState(auth);
const router = useRouter();
if (loading) return 'loading'
else if (error) return error
else if (user) {
router.push('/');
}
const authConfig = uiConfig(auth);
return (
<>
<Head>
<title>Login</title>
</Head>
<StyledFirebaseAuth uiConfig={authConfig} firebaseAuth={auth} />
</>
)
}
I think the example code you copy from uses module 8
try to import GoogleAuthProvider like this, check firebase ref
import { GoogleAuthProvider} from "firebase/auth"
...
...
export const uiConfig = (firebase) => {
return {
signInFlow: "popup",
signInSuccessUrl: "/",
signInOptions: [GoogleAuthProvider.PROVIDER_ID],
};
};
Related
I couldn't find an answer For Web V9, all I'm trying to do is to delete an image from Firebase-Storage using the URL not the image name as demonstrated in their Docs here
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getDatabase } from "firebase/database";
import { getFirestore } from "firebase/firestore";
import { getStorage } from "firebase/storage";
const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_KEY,
authDomain: ".....",
databaseURL: ".....",
projectId: ".......",
storageBucket: "......",
messagingSenderId: ".......",
appId: ".......",
measurementId: "......"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const database = getDatabase(app);
export const firestore = getFirestore(app);
export const storage = getStorage(app)
export const auth = getAuth()
So this is the code that I have tried
import { firestore, storage, database } from "../../firebase"
import { deleteObject, ref } from "firebase/storage";
import { storage } from "./firebase";
const SingleApplication = () => {
function delete(){
const ImgUrl = "https://firebasestorage.googleapis.com:443/v0/b/......appspot.com/o/Application-Imeges%2F09........"
const dImgRef = ref(storage, ImgUrl) //ImgUrl is a firebase sotrage url
deleteObject(dImgRef).then(() =>{
console.log("deleted")
})
}
return (
<div className='Main'>
</div>
)
}
export default SingleApplication
and the error was:
Firebase Storage: Invalid URL 'https://firebasestorage.googleapis.com:443/v0/b/......appspot.com/o/Application-Imeges%2F09F501.......'
I'm using react JSX
give permission to delete the file on firebase storage rules
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /folder1/{image} {
allow read: if true
...
allow delete: if true
}
}
}
then
import { deleteObject, ref } from "firebase/storage"
const pathImage = "folder1/image.jpg" // your path
const reference = ref(storage, pathImage)
deleteObject(reference).then().catch()
I am writing a React app with firebase version 9.6.9 for a login system, but this error keeps getting in my way. I have already tried this method:
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import { async } from '#firebase/util';
import { firebase } from "firebase/app";
import { getAuth, onAuthStateChanged, connectAuthEmulator,
signInWithEmailAndPassword, createUserWithEmailAndPassword,
signOut } from "firebase/auth";
export const firebaseApp = initializeApp({
//Configuration stuff
});
if (firebase.apps.length === 0/*or !firebase.apps.length*/) {
firebase.initializeApp(firebaseConfig);
}`
My current code looks like this:
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import { async } from '#firebase/util';
import { firebase } from "firebase/app";
import { getAuth, onAuthStateChanged, connectAuthEmulator,
signInWithEmailAndPassword, createUserWithEmailAndPassword,
signOut } from "firebase/auth";
export const firebaseApp = initializeApp({
//Configuration stuff
});
export const app = initializeApp(firebaseApp);
export const analytics = getAnalytics(app);
export const auth = getAuth(firebaseApp);
Any suggestions?
Why are you initializing your firebase app twice?
export const firebaseApp = initializeApp({
//Configuration stuff
});
export const app = initializeApp(firebaseApp); <- remove this line
you need to make sure that your firebase app is initialized only once, change your code to this:
export const firebaseApp = !getApps().length ? initializeApp(firebaseConfig) : getApp();
don't forget to import getApps() and getApp()
import { getApp, getApps, initializeApp } from 'firebase/app';
and by the way, you don't need to export const firebaseApp since you're not going to use it out of that file.
Look like this :
import firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
const firebaseConfig = {
apiKey: 'XXXXXXXXXXXXXX',
authDomain: 'XXXX.firebaseapp.com',
databaseURL: 'https://dburl.firebaseio.com',
projectId: 'proj-XXXX',
storageBucket: 'XXXXX.appspot.com',
messagingSenderId: 'XXXXXXX',
appId:XXXXXXXXXXXXXXXXXX"
};
firebase.initializeApp(firebaseConfig);
export const firebaseAuth = firebase.auth();
export const firestore = firebase.firestore()
then use :
import { firebaseAuth } from 'firebase'
const CustomComponent = props => {
const [email, setEmail] = useState()
const [password, setPassword] = useState()
const handleAuth = e => {
firebaseAuth.signInWithEmailAndPassword(email, password).then(res => {
console.log(res.user)
}).catch(err => {
const { code, message } = err
console.log(code, message)
})
}
return (<button onClick={handleAuth}>firebase</button>)
I am using NextJs version 12.0.10 and firebase version 9.6.6 which use a modular system to import it.
When I run the function from my service to fetch data from firebase/firestore, it returns an error saying Cannot access 'getStories' before initialization. I'm confident all the logic & syntax are correct, as it works perfectly when I fetch it from inside the page render function.
Here is my getServerSideProps function:
pages/index.js
import '#uiw/react-markdown-preview/markdown.css';
import { useContext } from 'react';
import { getStories } from '../lib/services/StoryService';
import { truncate } from 'lodash';
import { convertSecondsToHumanReadableDiff } from '../lib/utils/common';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { AuthContext } from '../pages/_app';
import Navigation from '../components/Navigation';
export async function getServerSideProps() {
const fetchedStories = await getStories();
const stories = fetchedStories.docs.map((story) => {
return {
...story.data(),
id: story.id,
content: truncate(story.data().content, { length: 150, separator: '...' }),
};
});
return { props: { stories } };
}
const Blog = ({ stories }) => {
const router = useRouter();
const { user } = useContext(AuthContext);
return (
<div>
...
</div>
);
};
export default Blog;
lib/firebase/firebase.js
import { initializeApp } from 'firebase/app';
import { getAnalytics } from 'firebase/analytics';
import { getFirestore } from 'firebase/firestore';
import { getAuth } from 'firebase/auth';
const firebaseConfig = {
apiKey: 'XXX',
authDomain: 'XXX',
projectId: 'XXX',
storageBucket: 'X',
messagingSenderId: 'XXX',
appId: 'XXX',
measurementId: 'XXX',
};
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
export const database = getFirestore(app);
export const auth = getAuth(app);
lib/services/storyService.js
import {
collection,
query,
getDocs,
getDoc,
setDoc,
doc,
serverTimestamp,
orderBy,
} from 'firebase/firestore';
import { database } from '../firebase/firebase';
import slugify from 'slugify';
import { random } from 'lodash';
const storiesRef = collection(database, 'stories');
export const createStory = async (payload) => {
const slugTitle = slugify(payload.title);
const slug = slugTitle + '-' + random(0, 100000);
const updatedPayload = {
...payload,
slug,
type: 'published',
createdAt: serverTimestamp(),
};
return setDoc(doc(storiesRef, slug), updatedPayload);
};
export const getStories = async () => {
const q = query(storiesRef, orderBy('createdAt', 'desc'));
return getDocs(q);
};
export const getStoryBySlug = async (slug) => {
const docRef = doc(database, 'stories', slug);
return getDoc(docRef);
};
You are using getDocs, a client-side function of firebase, inside your getStories function, which is invoked in getServerSideProps, a node.js environment.
Instead you need to use the admin SDK for functions invoked in node.js environment (like getServerSideProps), e.g. like so:
import * as admin from "firebase-admin/firestore";
export const getStories = async () => {
return await admin
.getFirestore()
.collection(database, 'stories')
.orderBy('createdAt', 'desc')
.get()
};
export const getStoryBySlug = async (slug) => {
return await admin
.getFirestore()
.doc(database, 'stories', slug)
.get()
};
(sorry for the late answer, I still hope it helps OP or anyone else)
I'm still learning and I've been following tutorials on firebase auth with reactjs. Now I'm branching off into functionalities the tutorial doesn't cover (anonymous sign-in & linking to google) and I think I'm not understanding correctly how to use firebase's linkWithPopup.
I'm getting TypeError: firebase__WEBPACK_IMPORTED_MODULE_1_.default.auth.GoogleAuthProvider is not a constructor when I try do it. Here is the code:
firebase.js
import firebase from 'firebase/app';
import 'firebase/auth'
import 'firebase/firestore'
const app = firebase.initializeApp({
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
})
export const auth = app.auth();
export default app;
AuthContext.js:
import React, { useContext, useState, useEffect } from 'react'
import firebase, { auth } from '../firebase'
const AuthContext = React.createContext();
export const useAuth = () => {
return useContext(AuthContext);
}
const AuthProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState();
const [loading, setLoading] = useState(true);
const anonLogin = () => {
return auth.signInAnonymously();
}
const linkWithGoogle = () => {
var googleProvider = new firebase.auth.GoogleAuthProvider();
auth.currentUser.linkWithPopup(googleProvider)
.then(() => {
console.log('linked correctly');
})
.catch(error => {
console.error(error);
})
}
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(user => {
setCurrentUser(user)
setLoading(false)
})
return unsubscribe
}, [])
const value = {
currentUser,
signup,
login,
logout,
resetPassword,
updateEmail,
updatePassword,
getUuid,
updateName,
anonLogin,
linkWithGoogle
}
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
);
}
}
Will appreciate any help I can get!
It looks like the Firebase reference is potentially a reference to your Firebase App rather than the Firebase library which contains the constructors for the providers.
try importing the Firebase library directly, or creating the providers inside your firebase.js file for you to export.
firebase.js
export const googleProvider = new firebase.auth.GoogleAuthProvider();
AuthContext.js
import firebase, { auth, googleProvider } from '../firebase'
I am using this version of firabaseSDK
"firebase": "^8.2.9",
"firebaseui": "^4.8.0"
typeError: Cannot read property 'PROVIDER_ID' of undefined
happens
I refer to this official tutorial.
https://firebase.google.com/docs/auth/web/google-signin
I tried several ways...but I couldn't do it with one way or another.
How should I fix it...
Config.js
import firebase from "firebase/app";
import "firebase/firestore";
import "firebase/auth";
import "firebase/storage";
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
var firebaseConfig = {
apiKey: "....",
authDomain: "...",
databaseURL: "https://...-rtdb.firebaseio.com",
projected: "...."
};
firebase.initializeApp(firebaseConfig);
firebase.firestore();
export default firebase;
import { Component } from 'react'
import { connect } from 'react-redux'
import { signIn } from '../../store/actions/authActions'
import { Redirect } from 'react-router-dom'
import StyledFirebaseAuth from 'react-firebaseui/StyledFirebaseAuth';
class SignIn extends Component {
state = {
email: '',
password: ''
}
uiConfig = {
signInOptions: [this.props.auth.GoogleAuthProvider.PROVIDER_ID],
};
render() {
const { authError ,auth} = this.props;
if (auth.uid) return <Redirect to='/' />
return (
<div className="container">
<StyledFirebaseAuth uiConfig={uiConfig} firebaseAuth={this.props.auth} />
</div>
)
}
}
const mapStateToProps = (state) => {
return {
authError: state.auth.authError,
auth: state.firebase.auth
}
}
const mapDispatchToProps = (dispatch) => {
return {
signIn: (creds) => dispatch(signIn(creds))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(SignIn)