Using Firebase Authentication (SDK 9) with Expo (v 8.5.0) - firebase

For the past week I have been encountering an error which is as follows: auth/invalid-email Firebase: Error (auth/invalid-email). To my understanding and to other Stacks and much time researching this, and using ChatGPT (no, it didn't work) the configuration file is correct and my code is correct, but clearly it isn't. I have gone over the Firebase docs several times, and it seems to check out, but again, clearly it doesn't. Anywho, here is the the firebaseConfig.js file (copied directly from Firebase docs).
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "myAPI Key",
authDomain: "myAuth Domain",
projectId: "myProjectID",
storageBucket: "myStorageBucket",
messagingSenderId: "myMessageSenderID",
appId: "myAppID",
measurementId: "myMeasurementID"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth();
export { auth };
Obviously, for security purposes I have an actual API Key where it belongs in the configuration.
Now here is where I believe my issue is, which is in the SignIn.js file.
import React, { useState } from 'react';
import { StyleSheet, Text, View, Button, TextInput } from 'react-native';
import tw from 'tailwind-react-native-classnames';
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from "../firebaseConfig";
export default function Home() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
let signIn = () => {
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
const user = userCredential.user;
console.log(user);
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
console.log(errorCode, errorMessage);
alert(errorMessage);
});
}
return (
<>
<Button title="Sign In" onPress={signIn} st />
<TextInput
style={tw`pl-4 h-12 w-80 border-black border-2 rounded-xl`}
placeholder="Email"
onChange={text => setEmail(text)}
value={email}
/>
<TextInput
style={tw`mt-4 pl-4 h-12 w-80 border-black border-2 rounded-xl`} placeholder="Password"
onChange={text => setPassword(text)}
value={password}
secureTextEntry={true}
/>
</>
);
}
Again, please keep in mind I am using expo. Additionally, here are the following dependencies, and versions I have installed to the root directory:
"dependencies": {
"#expo-google-fonts/open-sans": "^0.2.2",
"#expo-google-fonts/open-sans-condensed": "^0.2.2",
"expo": "~47.0.12",
"expo-app-loading": "~2.1.1",
"expo-font": "~11.0.1",
"expo-status-bar": "~1.4.2",
"firebase": "^9.16.0",
"react": "18.1.0",
"react-native": "0.70.5",
"tailwind-react-native-classnames": "^1.5.1"
},
"devDependencies": {
"#babel/core": "^7.12.9",
"autoprefixer": "^10.4.13",
"postcss": "^8.4.21",
"tailwindcss": "^3.2.4"
}
},
EDIT: Not sure if it matters to let you know or not, but I am using metro as it was mentioned to use on the expo docs for firebase. Here is the the metro.config.js file
const { getDefaultConfig } = require('#expo/metro-config');
const defaultConfig = getDefaultConfig(__dirname);
defaultConfig.resolver.assetExts.push('cjs');
module.exports = defaultConfig;

So after reading it over and over and doing even more research the code I had was correct. However, there was an error coming from the SignIn.js file specifically from the <TextInputs> Instead of doing onChange={text => setEmail(text)} it should be onChangeText={text => setEmail(text)}. The reason for this is the onChangeText, to my understanding is that it recalls the function for every new text is entered/updated.
For more information about onChange vs. onChangeTextis at this Stack which explains the major difference.

Related

Component auth has not been registered yet - SolidJS & Firebase

I'm using SolidJS with solid-firebase npm package. Just as a test I'm using the code from the git repo but when configured with my firebase project I get the error Component auth has not been registered yet
App.tsx
import type { Component } from 'solid-js'
import { Match, Switch } from 'solid-js'
import { GoogleAuthProvider, getAuth, signInWithPopup } from 'firebase/auth'
import { useAuth, useFirebaseApp } from 'solid-firebase'
const Login: Component = () => {
const app = useFirebaseApp()
const signIn = () => signInWithPopup(getAuth(app), new GoogleAuthProvider())
return <button onClick={signIn}>Sign In with Google</button>
}
const App: Component = () => {
const app = useFirebaseApp()
const state = useAuth(getAuth(app))
return (
<Switch>
<Match when={state.loading}>
<p>Loading...</p>
</Match>
<Match when={state.error}>
<Login />
</Match>
<Match when={state.data}>
<h1>Logged In</h1>
</Match>
</Switch>
)
}
export default App
index.tsx (firebaseConfig hidden)
import { render } from 'solid-js/web'
import { FirebaseProvider } from 'solid-firebase'
import './index.css'
import App from './App'
const root = document.getElementById('root')!
const firebaseConfig = {
apiKey: ...,
authDomain: ...,
projectId: ...,
storageBucket: ...,
messagingSenderId: ...,
appId: ...,
measurementId: ...,
}
if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
throw new Error(
'Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got mispelled?'
)
}
render(
() => (
<FirebaseProvider config={firebaseConfig}>
<App />
</FirebaseProvider>
),
root
)
The code above is straight from the git repo https://github.com/wobsoriano/solid-firebase. Only change is my firebase config.
When I run npm run dev and go to localhost:3000/ I get a blank page with this error in the console.

Next auth email provider is not triggering

Next-Auth has been working great for me until i decided to create a custom signIn page.
I have google login working perfectly and i can see lots going on in the debugger around token generation and session creation with my adapter.
However, when I try to sign in using email verification it just clears the email from the input box and then does nothing. The Form is straight out of the next auth docs.
I have triple checked the settings for my sendgrid apikey and they are all set correctly in my .env.local file.
"/pages/api/auth/[...nextauth].js"
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
import EmailProvider from "next-auth/providers/email"
import { FirestoreAdapter } from "#next-auth/firebase-adapter"
const authOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
}),
EmailProvider({
server: {
host: process.env.EMAIL_SERVER_HOST,
port: process.env.EMAIL_SERVER_PORT,
auth: {
user: process.env.EMAIL_SERVER_USER,
pass: process.env.EMAIL_SERVER_PASSWORD,
}
},
from: process.env.EMAIL_FROM
}),
],
session: {
jwt: true,
},
adapter: FirestoreAdapter({
apiKey: process.env.FIREBASE_API_KEY,
appId: process.env.FIREBASE_APP_ID,
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_SENDER_ID
}),
theme: ({
colorScheme: "dark",
}),
pages: {
signIn: "/auth/signin",
newUser: "/auth/signup",
},
debug: true,
callbacks: {
async signIn({ user, account, profile, email, credentials }) {
return true
},
async redirect({ url, baseUrl }) {
return baseUrl
},
async session({ session, user, token }) {
return session
},
async jwt({ token, user, account, profile, isNewUser }) {
return token
}
}
}
export default NextAuth(authOptions)
Here is my custom page...
"/pages/auth/signin.js"
import React from 'react'
import {getProviders, signIn, getCsrfToken} from 'next-auth/react'
import styles from '../../styles/signin.module.css'
import Logo from '../../components/Logo'
export default function SignIn ({ csrfToken, providers }) {
return (
<div>
<div className={styles.content}>
<div className={styles.cardWrapper}>
<Logo className={styles.logo}/>
<div className={styles.cardContent}>
<div className={styles.emailForm}>
<form method="post" action="/api/auth/signin/email">
<input name="csrfToken" type="hidden" defaultValue={csrfToken} />
<input type="text" id="email" name="email" placeholder="Email" />
<button type="submit">Sign in with Email</button>
</form>
</div>
<hr />
{Object.values(providers).map((provider) => {
if (provider.name === "Email") {
return
}
return (
<div key={provider.name}>
<button onClick={() => signIn(provider.id)}>
Sign in with {provider.name}
</button>
</div>
)
})}
</div>
</div>
</div>
</div>
)
}
export async function getServerSideProps(context) {
const csrfToken = await getCsrfToken(context)
const providers = await getProviders(context)
return {
props: { csrfToken },
props: { providers },
}
}
EDIT: Installed Dependencies
"next": "^12.2.5",
"next-auth": "^4.10.3",
"nodemailer": "^6.7.8",
"react": "18.2.0",
"react-dom": "18.2.0",
"swiper": "^8.3.2",
"swr": "^1.3.0"
"#next-auth/firebase-adapter": "^1.0.1",
"#types/node": "^18.7.13",
"core-js": "^3.25.0",
"firebase": "^9.9.3",
"fs": "^0.0.1-security",
EDIT: ENV SETTINGS
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=REDACTED SECRET
EMAIL_SERVER_HOST=smtp.sendgrid.net
EMAIL_SERVER_PORT=587
EMAIL_SERVER_USER=apikey
EMAIL_SERVER_PASSWORD=REDACTED (SET AS THE API KEY PROVIDED BY SENDGRID)
EMAIL_FROM=REDACTED (SET AS VERIFIED SINGLE USER EMAIL ADDRESS IN SENDGRID)
Also set are the following...
FIREBASE_API_KEY=REDACTED
FIREBASE_AUTH_DOMAIN=REDACTED
FIREBASE_PROJECT_ID=REDACTED
FIREBASE_STORAGE_BUCKET=REDACTED
FIREBASE_MESSAGING_SENDER_ID=REDACTED
FIREBASE_APP_ID=REDACTED
FIREBASE_DATABASE_URL=REDACTED
EDIT: "/pages/_app.js" - Added main app just in case the problem is being caused by the way I have wrapped my component.
import React from 'react'
import App from 'next/app'
import { SessionProvider } from "next-auth/react"
import Layout from "../components/Layout.js"
import AccountSettingsLayout from '../components/AccountSettingsLayout'
import { SWRConfig } from 'swr'
import '../styles/globals.css'
class MyApp extends App {
render() {
const { Component, router, pageProps: { session, ...pageProps }} =
this.props
if (router.pathname.startsWith('/auth/')) {
return (
<React.StrictMode>
<SessionProvider session={session}>
<SWRConfig>
<AccountSettingsLayout>
<Component {...pageProps} />
</AccountSettingsLayout>
</SWRConfig>
</SessionProvider>
</React.StrictMode>
)
}
return (
<React.StrictMode>
<SessionProvider session={session}>
<SWRConfig>
<Layout>
<Component {...pageProps} />
</Layout>
</SWRConfig>
</SessionProvider>
</React.StrictMode>
)
}}
export default MyApp
UPDATE: when the email address is entered and the submit is clicked i get the following change in the URL.
starting URL = http://localhost:3000/auth/signin
after submit= http://localhost:3000/auth/signin?callbackUrl=http%3A%2F%2Flocalhost%3A3000
UPDATED 30.08.2022 -
I can see in terminal the following...
wait - compiling /_error (client and server)...
However the event compiles straight after without any error being displayed.
I read in the next.js docs that the payload for email must 2 entries, the CSRF token and the email address. I can see in the browser tools that the CSRF token is generated. I can also see in the network tab that the payload shows the email address but the CSRF Token is blank on submission.
Thanks in advance for any help on this one. Go easy on me as I am a new coder!
Ok so the problem was with my getServerSideProps...
BEFORE:
export async function getServerSideProps(context) {
const csrfToken = await getCsrfToken(context)
const providers = await getProviders(context)
return {
props: { csrfToken },
props: { providers },
}
}
AFTER:
export async function getServerSideProps(context) {
const csrfToken = await getCsrfToken(context)
const providers = await getProviders(context)
return {
props: { csrfToken, providers },
}
}
I noticed that the csrfToken was not being passed into the email submit payload.
For others in future...using chrome devtools if you inspect your page prior to clicking submit then you can click on network and check the payload and header.

Issue while implementing firebaseUi auth in a nextjs project ? [error : window is not defined]

I'm trying to setup firebase Auth into my nextjs project (it looks like the firebase documentation is not up-to-date via the release of the getAuth method).
While using firebaseUi (to get the automatic styling of the different auth providers), I get this error :
Here is the code (i'm just trying to render the firebaseUi component for now) :
import { initializeApp } 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
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// Initialize Cloud Firestore
const db = getFirestore(app);
// Initialize Firebase Authentication
const auth = getAuth(app);
export { db, auth }
Then in a template page for signin :
import { NavBar } from '../components';
import { StyledFirebaseAuth } from 'react-firebaseui/StyledFirebaseAuth';
import { auth } from '../firebase/initFirebase';
import { GoogleAuthProvider } from 'firebase/auth';
const firebaseui = require('firebaseui')
// // Initialize the FirebaseUI Widget using Firebase.
var ui = new firebaseui.auth.GoogleAuthProvider(auth);
function Signup() {
const firebaseUiConfig = {
signInFlow: 'popup',
signInSuccessUrl: '/',
tosUrl: '/terms-of-service',
privacyPolicyUrl: '/privacy-policy',
signInOptions: [
GoogleAuthProvider.PROVIDER_ID
]
}
return (
<div>
<NavBar />
<StyledFirebaseAuth uiConfig={firebaseUiConfig} firebaseAuth={auth} />
</div>
)
}
export default Signup
Thanks a lot in advance for your help, I don't understand what's going on :(
// EDIT //
I understand it has to deal with SSR. So I did try to dynamically import firebaseUi with next/dynamic. I don't get the error any longer but the page is now blank (just the navbar component renders). Is it because I am passing props inappropriately ?
import dynamic from "next/dynamic";
import { NavBar } from '../components';
import { auth } from '../firebase/initFirebase';
import { GoogleAuthProvider } from 'firebase/auth';
const AuthComponent = dynamic(() =>
import('react-firebaseui/StyledFirebaseAuth').then((mod) => mod.StyledFirebaseAuth)
)
function Signup() {
const firebaseUiConfig = {
// signInFlow: 'popup',
signInSuccessUrl: '/',
tosUrl: '/legal',
privacyPolicyUrl: '/legal',
signInOptions: [
GoogleAuthProvider.PROVIDER_ID
]
}
return (
<div>
<NavBar />
<AuthComponent uiConfig={firebaseUiConfig} firebaseAuth={auth} />
</div>
)
}
export default Signup
The idea here to disable SSR on the page which used firebaseui.
This can be done in two steps.
Use firebase ui or any library which needs window keywork to work.
import React from 'react';
import Modal from '#leafygreen-ui/modal';
import * as firebaseui from 'firebaseui'
import 'firebaseui/dist/firebaseui.css'
export default function AuthUi({open, setOpen}) {
return (
<>
<Modal open={open} setOpen={setOpen}>
// Modal Content goes here.
// Signup widgets comes here
</Modal>
</>
);
}
while importing the library, do something like this.
//__app.js
// import AuthUi from '../components/authUi'; >> Replace this by code below
import dynamic from 'next/dynamic'
const AuthUi = dynamic(
() => import('../components/authUi'),
{ ssr: false }
);
Now you would be able to use firebaseui without window error.

How do I configure SvelteKit to use Firebase Auth?

I have it working with Firebase 8, but I can't seem to get Firebase 9 working...
Here is my firebaseConfig.js file:
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
const firebaseConfig = {
apiKey: 'AIzaSyCAAngD7340_noXs7eesCfE9Y3cwqmiZhU',
authDomain: 'svelte-todo-20f21.firebaseapp.com',
projectId: 'svelte-todo-20f21',
storageBucket: 'svelte-todo-20f21.appspot.com',
messagingSenderId: '402466412167',
appId: '1:402466412167:web:c739e7eb86fc5b6ac5ca22',
measurementId: 'G-2N348J0NTE'
};
const firebaseApp = initializeApp(firebaseConfig);
export const auth = getAuth(firebaseApp);
export const firestore = getFirestore(firebaseApp);
export default firebaseApp;
My auth.js file:
import { auth } from './firebaseConfig';
import { GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
// Sign in with popup && Google as the provider
const googleProvider = new GoogleAuthProvider();
export const googleSignIn = async () => {
await signInWithPopup(auth, googleProvider)
.then((user) => {
console.log(user);
})
.catch((error) => {
console.error(error);
});
};
And the index.svelte:
<script>
import { googleSignIn } from '../auth';
</script>
<button on:click={() => googleSignIn()}>Sign In</button>
Seems easy enough but I'm getting this error that I can't resolve...
"500
The requested module '/node_modules/.vite/firebase_firestore.js?v=42dbe183' does not provide an export named 'getFirestore'
SyntaxError: The requested module '/node_modules/.vite/firebase_firestore.js?v=42dbe183' does not provide an export named 'getFirestore'"
If it helps, someone suggested that I update my svelte.config.js file to the following...
/** #type {import('#sveltejs/kit').Config} */
const config = {
kit: {
// hydrate the <div id="svelte"> element in src/app.html
target: '#svelte',
vite: {
ssr: {
external: ['firebase']
}
}
}
};
export default config;

FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp()

Hey I am pulling my hair out on this one - I have read several posts here but keep getting this error here is my code for init.js
import firebase from "firebase/app"
var config = {
apiKey: "AIzaSyAF2VbjdWbQdsdsdk79nINQV5wdsdBn-uMy844gY7s",
authDomain: "lcarchivewebsite.firebaseapp.com",
databaseURL: "https://lcarchivewebsite.firebaseio.com",
projectId: "lcarchivewebsite",
storageBucket: "lcarchivewebsite.appspot.com",
messagingSenderId: "71812947145517",
appId: "1:718129478445517:web:0284d6bsdsdbb57384c87800c4"
};
firebase.initializeApp(config);
export const firestore = firebase.firestore()
export const db = firebase.database()
export const auth = firebase.auth()
export const storage = firebase.storage()
my component is here:
<template>
<h2>hello</h2>
</template>
<script>
import storage from 'firebase'
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
created(){
var storageRef = storage.storage().ref()
var listRef = storageRef.child('2020')
listRef.listAll().then((response) => {console.log(response)})
}
}
</script>
i have installed firebase with npm install --save
here is package.json
"dependencies": {
"firebase": "^7.17.1",
"materialize-css": "^1.0.0",
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"webpack-cli": "^3.3.12"
},
Couple of problems here, the first being that you are importing from the firebase lib in node_modules where you should be importing the storage you exported from your init.js script.
Fix this with
import { storage } from '#/path/to/init.js' // "#" refers to your "src" directory
// snip
var storageRef = storage.ref()
The other problem is that in order to use Firebase features like storage, you need to import those libs. So in init.js...
import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/database'
import 'firebase/firestore'
import 'firebase/storage'

Resources