Redirect to Login Page after Login-with-google & User's credential are not passing through Firebase Authentication

122 Views Asked by At

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.

0

There are 0 best solutions below