I have a React Native app that needs to be served on its web version. So, I need to implement the Google OAuth with the firebase js lib.
I'm following these steps.
If I use the same code from the docs I have a weird error (of course I put the proper config object in the initializeApp method):
import * as React from 'react';
import * as WebBrowser from 'expo-web-browser';
import { ResponseType } from 'expo-auth-session';
import * as Google from 'expo-auth-session/providers/google';
import { initializeApp } from 'firebase/app';
import { getAuth, GoogleAuthProvider, signInWithCredential } from 'firebase/auth';
import { Button } from 'react-native';
// Initialize Firebase
initializeApp({
/* Config */
});
WebBrowser.maybeCompleteAuthSession();
export default function App() {
const [request, response, promptAsync] = Google.useIdTokenAuthRequest(
{
clientId: 'Your-Web-Client-ID.apps.googleusercontent.com',
},
);
React.useEffect(() => {
if (response?.type === 'success') {
const { id_token } = response.params;
const auth = getAuth();
const credential = GoogleAuthProvider.credential(id_token);
signInWithCredential(auth, credential);
}
}, [response]);
return (
<Button
disabled={!request}
title="Login"
onPress={() => {
promptAsync();
}}
/>
);
}
The error is:
I get this error specifically when I call signInWithCredential()
The strange thing is that in the Network tab (Chrome DevTools) I have a successful response:
And the problem is: If I want to get the user information with onAuthStateChanged, it is null because the login attempt just failed (despite the dev-tools being all good)
Note: I've tried with a new starter project, moving our dependencies with the same version as they are here and it's working.
But I can't figure out what can be happening with this project.
EDIT: Adding images of the requests that are being made:
Related
I can't firebase v9 enableIndexedDbPersistence in a nextjs pwa.
this erros are trow
index.js // firebase main
import { initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'
import { getFirestore } from 'firebase/firestore'
import { getStorage } from 'firebase/storage'
const firebaseConfig =
process.env.NEXT_PUBLIC_FIREBASE_CONFIG
const app = initializeApp(JSON.parse(firebaseConfig))
export const db = getFirestore(app)
// enableIndexedDbPersistence(db) // >>> if put here it said can't be invoked after getFirestore or any other funtion
export const auth = getAuth(app)
export const storage = getStorage(app)
So where should i invoke
The enableIndexedDbPersistence(db) function must be called before . From its documentation:
Must be called before any other functions (other than
{#link initializeFirestore}, {#link (getFirestore:1)} or
{#link clearIndexedDbPersistence}.
So getFirestore(app) is actually exempted from that, in contrast what you stated in the comment of your code snipped:
// >>> if put here it said can't be invoked after getFirestore or any other function
Consequently, my guess would be that you might use the exported db before the promise of enableIndexedDbPersistence(db) completes.
You could resolve this in different ways, such as wrapping it in a service or method and make sure you are await-ing the promise, or generally change your app that db is not used right away.
In my Ionic PWA app, I'm successfully using the following:
import { getFirestore, enableIndexedDbPersistence } from "firebase/firestore";
import { initializeApp } from "firebase/app";
const firebaseConfig = {
// ...
};
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
enableIndexedDbPersistence(db)
.then(() => console.log("Enabled offline persistence"))
.catch((error) => {
if (error.code == "failed-precondition") {
// Multiple tabs open, persistence can only be enabled
// in one tab at a a time.
// ...
} else if (error.code == "unimplemented") {
// The current browser does not support all of the
// features required to enable persistence
// ...
}
});
This is very similar to your snipped indeed. But the first access to Firestore happens after via user interaction, and not right away.
I am pretty new to React Native; I have been trying to add google authentication via firebase and I keep running into this warning:
[Unhandled promise rejection: ReferenceError: Can't find variable: auth]
at node_modules\#babel\runtime\helpers\regeneratorRuntime.js:86:13 in tryCatch
at node_modules\#babel\runtime\helpers\regeneratorRuntime.js:66:31 in <anonymous>
at node_modules\#babel\runtime\helpers\regeneratorRuntime.js:86:13 in tryCatch
at node_modules\#babel\runtime\helpers\regeneratorRuntime.js:124:27 in invoke
at node_modules\#babel\runtime\helpers\regeneratorRuntime.js:148:16 in PromiseImpl$argument_0
at node_modules\promise\setimmediate\core.js:45:6 in tryCallTwo
at node_modules\promise\setimmediate\core.js:200:22 in doResolve
at node_modules\promise\setimmediate\core.js:66:11 in Promise
at node_modules\#babel\runtime\helpers\regeneratorRuntime.js:147:15 in callInvokeWithMethodAndArg
at node_modules\#babel\runtime\helpers\regeneratorRuntime.js:152:154 in _invoke
at node_modules\#babel\runtime\helpers\regeneratorRuntime.js:238:57 in exports.async
at node_modules\promise\setimmediate\core.js:37:13 in tryCallOne
at node_modules\promise\setimmediate\core.js:123:24 in setImmediate$argument_0
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:123:14 in _callTimer
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:177:14 in _callImmediatesPass
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:437:30 in callImmediates
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:388:6 in __callImmediates
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:132:6 in __guard$argument_0
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:365:10 in __guard
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:131:4 in flushedQueue
Here is my code:
import React, { createContext, useContext } from 'react';
import * as Google from "expo-google-app-auth";
import{
GoogleAuthProvider,
onAuthStateChanged,
signInWithCredential,
signOut,
} from "#firebase/auth";
const AuthContext = createContext({});
const config = {
androidClientId: key,
iosClientId: key,
scopes: ['profile', 'email'],
permissions: ['public_profile', 'email', 'gender', 'location'],
}
export const AuthProvider = ({children}) => {
const signInWithGoogle = async () => {
await Google.logInAsync(config).then(async (logInResult) => {
if(logInResult.type === 'success'){
const { idToken, accessToken } = logInResult;
const credential = GoogleAuthProvider.credential(idToken, accessToken);
await signInWithCredential(auth, credential);
}
return Promise.reject();
});
};
return (
<AuthContext.Provider value ={{
user: null,
signInWithGoogle
}}
>
{children}
</AuthContext.Provider>
);
};
export default function useAuth() {
return useContext(AuthContext);
}
I pass the variable auth here:
await signInWithCredential(auth, credential);
However, no users show up on the authentication page of firebase, and I keep receiving this warning.
Thanks for your help!
As the error says, you're trying to pass an auth variable to signInWithCredential, but you don't declare or initialize it anywhere. As shown in the documentation on getting started with Firebase Authentication on the web, you can get this with:
import { getAuth } from "firebase/auth";
// TODO: Replace the following with your app's Firebase project configuration
// See: https://firebase.google.com/docs/web/learn-more#config-object
const firebaseConfig = {
// ...
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// Initialize Firebase Authentication and get a reference to the service
const auth = getAuth(app);
Please refer to the official documentation provided by firebase for google auth
The google-signin library provides a wrapper around the official Google login library, allowing you to create a credential and sign-in to Firebase.
Most configuration is already setup when using Google Sign-In with Firebase, however you need to ensure your machines SHA1 key has been configured for use with Android. You can see how to generate the key on the Getting Started documentation.
Ensure the "Google" sign-in provider is enabled on the Firebase Console.
Follow these instructions to install and setup google-signin
Before triggering a sign-in request, you must initialize the Google SDK using your any required scopes and the webClientId, which can be found in the android/app/google-services.json file as the client/oauth_client/client_id property (the id ends with .apps.googleusercontent.com). Make sure to pick the client_id with client_type: 3
import { GoogleSignin } from '#react-native-google-signin/google-signin';
GoogleSignin.configure({
webClientId: '',
});
Once initialized, setup your application to trigger a sign-in request with Google using the signIn method.
import React from 'react';
import { Button } from 'react-native';
function GoogleSignIn() {
return (
<Button
title="Google Sign-In"
onPress={() => onGoogleButtonPress().then(() => console.log('Signed in with Google!'))}
/>
);
}
The onGoogleButtonPress can then be implemented as follows:
import auth from '#react-native-firebase/auth';
import { GoogleSignin } from '#react-native-google-signin/google-signin';
async function onGoogleButtonPress() {
// Get the users ID token
const { idToken } = await GoogleSignin.signIn();
// Create a Google credential with the token
const googleCredential = auth.GoogleAuthProvider.credential(idToken);
// Sign-in the user with the credential
return auth().signInWithCredential(googleCredential);
}
Upon successful sign-in, any onAuthStateChanged listeners will trigger with the new authentication state of the user.
This is my first time asking a question on StackOverflow. I am making a school project and I am a beginner at Firebase and JavaScript. I am trying to make a Tinder clone. React is telling me there's an error in this part of my code. At first I had different errors but they were Firebase syntax related and I promptly fixed them but now I don't have a clue on what this error means. My code works on localhost for a split second (I see my application) and then the error appears.
import React, { useEffect, useState } from 'react';
import TinderCard from 'react-tinder-card';
import database from './firebase';
import './SwipeCards.css';
...
function SwipeCards() {
...
useEffect(() => {
database.collection('buddies').onSnapshot((snapshot) => setBuddies(snapshot.docs.map((doc) => doc.data())));
}, []);
...
}
I've tried two solutions of similar problems other people had, namely:
(in my tinderCards.js)
database.firestore().collection('buddies')...
and (in my firebase.js)
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
...
const firebaseApp = initializeApp(firebaseConfig);
const database = getFirestore(firebaseApp);
export default database;
But both didn't work. I can post more of the code if needed. Any help would be greatly appreciated.
You are using the new modular SDK (v9) which no longer uses firebase.firestore() namespace. I'd recommend following the documentation to learn about new syntax:
import database from './firebase';
import { doc, onSnapshot, collection, query, where, onSnapshot } from "firebase/firestore";
useEffect(() => {
const q = query(collection(db, "buddies"))
const unsub = onSnapshot(q, (querySnapshot) => {
console.log("Data", querySnapshot.docs.map(d => doc.data()));
});
}, [])
I'm using Google firebase v9. On the first sign in, usually there would be a pop up for user to choose which email to sigh in with, but for some reason, when I sign in, it automatically send me to the chat page automatically. I tried delete user in my firebase app and tried again and get the same result. What am I doing wrong?
firebase.js:
import { GoogleAuthProvider } from 'firebase/auth';
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
const firebaseConfig = {//myap config};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const provider = new GoogleAuthProvider();
export { auth, provider };
login-page:
import { auth, provider } from '../firebase';
import { useAuthState } from 'react-firebase-hooks/auth';
import { useNavigate } from 'react-router-dom';
import { signInWithPopup } from 'firebase/auth';
function Header(){
const [user] = useAuthState(auth);
const navigate = useNavigate();
const signIn = (e) => {
signInWithPopup(auth, provider)
.then(() => navigate('/channel'))
.catch((error) => alert(error.message));
};
return (
<buttononClick={!user ? signIn : () => navigate('/channel')}>Login</button/>
);
};
Maybe It's because I am already sign-in on chrome? If someone can check my code and verified, that would be awesome.
It sounds like your app is already associated with your Google account. Signing out does not sever that association.
Removing that association is described in the Remove third-party account access, but mostly consists of going to the list of Third-party apps with account access and removing your app from that list.
If that doesn't do it, have a look at the results on forcing the account picker to show up.
I uploaded my app to Play Store without any problem. However, when I tried to install the App Store, the application was rejected and I received the following message.
Guideline 2.1 - Performance - App Completeness
We discovered one or more bugs in your app. Specifically, the app
displayed only a splash screen.
Review device details:
Device type: iPhone
OS version: iOS 15.1
I tried the application both on the simulator and on the real device with testflight. But I have never encountered such a problem. Does anyone know the reason or are having the same problem?
I've done almost the same application before. The only difference is that I add anonymousSignIn() in this app. Is this what broke the app or is there something else? Here my splash screen codes:
import React, { useEffect } from 'react'
import AsyncStorage from "#react-native-async-storage/async-storage"
import { View } from 'react-native'
import AppIcon from '../../assets/svgs/app-icon.svg'
import styles from './styles/SplashStyles'
import { RemoteConfig } from '../../api/RemoteConfig'
import { getData } from '../../api/RealtimeDb'
import { NotificationUtil } from "../../utils/NotificationUtil"
import { InitializeUtil } from "../../utils/InitializeUtil"
import { pushNotification } from '../../api/PushNotification';
import { anonymousSignIn } from '../../api/Auth'
const remoteConfig = new RemoteConfig()
const notificationUtil = new NotificationUtil()
const initializeUtil = new InitializeUtil()
const Splash = ({ navigation }) => {
// asking user for notification permission (iOS)
function permission() {
notificationUtil.pushNotificationAPNsPermissions()
}
useEffect(() => {
async function splash() {
// fetches the remote config data from firebase
remoteConfig.init()
pushNotification()
//message to be shown in the alert
const message = remoteConfig.getAlertMessage().text
// alert before notification permission
await notificationUtil.alertBeforeNotificationPermission(
message,
permission
)
await anonymousSignIn()
getData()
.then(async (response) => {
const lastViewedWord = await AsyncStorage.getItem("lastViewedWord")
const page = await initializeUtil.getPageNameToVisit()
navigation.reset({
index: 0,
routes: [{
name: page, params: {
lastViewedWord: lastViewedWord,
allData: response,
}
}]
})
})
}
splash()
}, [])
return (
<View style={styles.container} >
<AppIcon
height='100%'
width='50%'
/>
</View >
)
}
export default Splash