signInWithCredential promise doesn’t resolve until user input (tap)

[REQUIRED] Describe your environment

  • Operating System version: React Native, replicated on both Android and iOS
  • Browser version: N/A
  • Firebase SDK version: 7.9.3 (also happened with 7.9.1, upgrade didn’t fix)
  • Firebase Product: Auth

[REQUIRED] Describe the problem

I’m calling signInWithCredential async, but the promise doesn’t resolve until a user input happens (tapping the screen). E.g. on the login screen, I login with Google, get the Google credential, get the Credential item from Auth.GoogleAuthProvider.credential, then call signInWithCredential. It will eventually resolve on its own, but that usually takes over 60 seconds, whereas if I tap the screen right after the call happens the promise resolves almost immediately (as seen in the console). I currently have an authentication loading screen in place but the bug also occurred without the loading screen (just waiting on the login screen until the promise resolves, either after a minute or with a tap).

Not getting any errors or warnings in the console, and after some testing I am sure that the hang is happening while waiting for the promise to resolve.

This is a problem for obvious UX reasons – I don’t want to hackily make the user tap the screen to finish sign in, and waiting 60 seconds to sign in is worse. Hoping to fix this to keep my code clean and the UX nice.

Steps to reproduce:

Using an Expo-created app, following their directions for Firebase authentication . The call succeeds and I get all relevant information, it’s just the promise that doesn’t resolve until the user taps the screen (or waits ~60 seconds). You can find those directions at https://docs.expo.io/versions/latest/guides/using-firebase/#user-authentication.

To reproduce, get a new CRNA app and set up Firebase authentication (relevant code copied below, link to docs tutorial above). Then sign in with signInWithCredential (am using Google credentials) and see this weird bug.

I think it’s a problem with the firebase JS sdk, but it’s also possible that I’m somehow implementing the promise wrong? Am somewhat new to JS/React Native so if there’s some stupid solution I’m missing I would love to know. Google hasn’t returned anything useful or recent in googling this error.

Relevant Code:

Here’s the relevant code from my App.js file:

async function _loginWithGoogle () {
    try {
      // Fetch Google keys
      const result = await Google.logInAsync({
        androidClientId:"KEYS",
        iosClientId:"KEYS",
        scopes: ["profile", "email"]
      });
  
      // If Google keys successfully retrieved, use them to auth with Firebase
      if (result.type === "success") {
        const { idToken, accessToken } = result;
        // Changes state to bring up an activity indicator / loading modal
        dispatch({ type: 'AUTH_LOADING', isAuthLoading: true });
        // FbAuth and FbLib are shorthands defined in my Firebase config. As mentioned, they work
        const credential = FbLib.auth.GoogleAuthProvider.credential(idToken, accessToken);
        await FbAuth.setPersistence(FbLib.auth.Auth.Persistence.LOCAL);
        // Hangs on the following promise - the promise doesn't return until I tap the screen
        // ...or wait ~50 seconds.
        let fbSigninResult = FbAuth.signInWithCredential(credential);
        console.log(fbSigninResult);
        return( await fbSigninResult )
      } else {
        return { cancelled: true };
      }
    } catch (err) {
      console.log("err from App.js:", err);
    }
  }

And here’s my package versions:

{
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "eject": "expo eject",
    "test": "node ./node_modules/jest/bin/jest.js --watchAll",
    "devtools": "react-devtools"
  },
  "jest": {
    "preset": "jest-expo"
  },
  "dependencies": {
    "@draftbit/ui": "^2.39.1-16",
    "@expo/samples": "2.1.1",
    "@expo/vector-icons": "^10.0.0",
    "@firebase/firestore": "^1.11.1",
    "@react-native-community/masked-view": "0.1.5",
    "@react-navigation/bottom-tabs": "^5.0.5",
    "@react-navigation/native": "^5.0.4",
    "@react-navigation/stack": "^5.0.4",
    "date-time-format-timezone": "^1.0.21",
    "expo": "^36.0.0",
    "expo-asset": "~8.0.0",
    "expo-cli": "^3.13.1",
    "expo-constants": "~8.0.0",
    "expo-font": "~8.0.0",
    "expo-google-app-auth": "^8.0.1",
    "expo-permissions": "~8.0.0",
    "expo-secure-store": "~8.0.0",
    "firebase": "^7.9.3",
    "grpc": "^1.20.2",
    "intl": "^1.2.5",
    "react": "16.9.0",
    "react-native": "https://github.com/expo/react-native/archive/sdk-36.0.1.tar.gz",
    "react-native-gesture-handler": "~1.5.0",
    "react-native-reanimated": "~1.4.0",
    "react-native-safe-area-context": "0.6.0",
    "react-native-screens": "2.0.0-alpha.12",
    "react-native-typography": "^1.4.0"
  },
  "devDependencies": {
    "@babel/core": "^7.8.4",
    "@babel/plugin-proposal-decorators": "^7.8.3",
    "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
    "@babel/plugin-proposal-optional-chaining": "^7.8.3",
    "@babel/plugin-proposal-pipeline-operator": "^7.8.3",
    "@babel/plugin-syntax-dynamic-import": "^7.8.3",
    "@babel/plugin-syntax-export-default-from": "^7.8.3",
    "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
    "@babel/plugin-syntax-import-meta": "^7.8.3",
    "@babel/plugin-syntax-numeric-separator": "^7.8.3",
    "@babel/preset-react": "^7.0.0",
    "babel-eslint": "^10.0.3",
    "babel-preset-expo": "^8.0.0",
    "babel-preset-react-native-stage-0": "^1.0.1",
    "eslint": "^5.16.0",
    "eslint-config-airbnb-base": "^14.0.0",
    "eslint-plugin-babel": "^5.3.0",
    "eslint-plugin-import": "2.20.1",
    "eslint-plugin-react": "^7.18.3",
    "eslint-plugin-react-hooks": "^2.4.0",
    "eslint-plugin-react-native": "^3.8.1",
    "jest-expo": "^36.0.0",
    "react-devtools": "^4.4.0"
  },
  "private": true
}

Glad to answer any questions or post somewhere else if this isn’t the correct venue.

2 thoughts on “signInWithCredential promise doesn’t resolve until user input (tap)

  1. Also encounter same issue, I use Facebok login with firebase and same expo version. So I think it’s not relevant to google or fb login. Please help.