This project is based on React Native Expo, and it is tested through the Expo-Go app on iOS & Android. I'm facing the same issue on both platforms. When I log in with Google, after the login process complete, I'm redirected to the login page, and also my credentials are not stored in Firebase Authentication.
Firebase Configuration:
Android Package Name: host.exp.exponent
iOS Bundle ID: host.exp.exponent
WebApp:
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
apiKey: "XXXX",
authDomain: "app-name.firebaseapp.com",
projectId: "app-name",
storageBucket: "app-name.appspot.com",
messagingSenderId: "XXXX",
appId: "X:XX:web:XXXX"
};
This provided WebApp credentials saved as firebase.js in root_directory,
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
// 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
const firebaseConfig = {
apiKey: "XXXX",
authDomain: "app-name.firebaseapp.com",
projectId: "app-name",
storageBucket: "app-name.appspot.com",
messagingSenderId: "XXXX",
appId: "X:XX:web:XXXX"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
export { auth, db };
Google Console Configuration:
For Android & iOS: default settings from Google Console through Firebase.
For the WebApp: I only added the Authorized redirect URIs as https://auth.expo.io/@user.name/SLUG because I was getting an 'Error 400: redirect_uri_mismatch' and left the rest as the default configuration from Google Console through Firebase.
Note: This WebApp configuration in Google Console was created by Firebase after I enabled Google Sign-in providers, not by the WebApp I created earlier on Firebase for my project."
Code from root_directory/hooks/useAuth.js,
import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { startAsync, makeRedirectUri } from 'expo-auth-session';
import * as Google from 'expo-auth-session/providers/google';
import { auth, firebase } from '../firebase';
import AsyncStorage from '@react-native-async-storage/async-storage';
import * as Crypto from 'expo-crypto';
const AuthContext = createContext({});
const request = {
androidClientId: 'Android_OAuth-2.0-Client-IDs.apps.googleusercontent.com',
iosClientId: 'iOS_OAuth-2.0-Client-IDs.apps.googleusercontent.com',
webClientId: 'Created_through_Firebase_Sign-In_providers_OAuth-2.0-Client-IDs.googleusercontent.com',
scopes: ['profile', 'email'],
permissions: ['public_profile', 'email', 'gender', 'location'],
};
export const AuthProvider = ({ children }) => {
const [error, setError] = useState(null);
const [user, setUser] = useState(null);
const [loadingInitial, setLoadingInitial] = useState(true);
const [loading, setLoading] = useState(false);
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
if (user) {
setUser(user);
} else {
setUser(null);
}
setLoadingInitial(false);
});
return () => unsubscribe();
}, []);
const logout = async () => {
setLoading(true);
try {
await auth.signOut();
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
const signInWithGoogle = async () => {
setLoading(true);
try {
const { type, params } = await startAsync({
authUrl: `https://accounts.google.com/o/oauth2/v2/auth?client_id=${request.webClientId}&redirect_uri=${encodeURIComponent(
makeRedirectUri({ useProxy: true })
)}&response_type=code&scope=${encodeURIComponent(request.scopes.join(' '))}`,
tokenUrl: 'https://oauth2.googleapis.com/token',
});
if (type === 'success') {
try {
const { code } = params;
const tokenResponse = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `code=${code}&client_id=${request.webClientId}&redirect_uri=${encodeURIComponent(
makeRedirectUri({ useProxy: true })
)}&grant_type=authorization_code`,
});
const tokenResult = await tokenResponse.json();
const nonce = await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
Math.random().toString(36).substring(2)
);
const credential = firebase.auth.GoogleAuthProvider.credential(tokenResult.id_token, tokenResult.access_token); // Use firebase.auth.GoogleAuthProvider.credential
await firebase.auth().signInWithCredential(credential);
await AsyncStorage.setItem('nonce', nonce);
} catch (error) {
setError(error);
}
}
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
const memoedValue = useMemo(
() => ({
user,
loading,
error,
signInWithGoogle,
logout,
}),
[user, loading, error]
);
return (
<AuthContext.Provider value={memoedValue}>{!loadingInitial && children}</AuthContext.Provider>
);
};
export default function useAuth() {
return useContext(AuthContext);
}
I don't know where the problem lies, whether it's in my code or the Firebase/Google Console configurations. I'll provide more details if you need any.