abiieez
abiieez

Reputation: 3189

Firebase reauthenticate during startup with Flutter

The idea is here to keep the user logged in even after the user has closed the app and relaunch it at much later time.

I have the following code which logs in user and then try to store the tokens

Future<User> loginSocialFirebaseGoogle() async {
    GoogleSignInAccount signInResult = await _googleSignIn.signIn();
    GoogleSignInAuthentication auth = await signInResult.authentication;
    final AuthCredential authCredential = GoogleAuthProvider.getCredential(
        idToken: auth.idToken, accessToken: auth.accessToken);
    final AuthResult authResult =
        await _auth.signInWithCredential(authCredential);
    final FirebaseUser firebaseUser = authResult.user;

    assert(!firebaseUser.isAnonymous);
    assert(await firebaseUser.getIdToken() != null);

    final FirebaseUser currentUser = await _auth.currentUser();
    assert(firebaseUser.uid == currentUser.uid);

    final SharedPreferences pref = await SharedPreferences.getInstance();
    pref.setString("idToken", auth.idToken);
    pref.setString("accessToken", auth.accessToken);
    pref.setString("provider", describeEnum(Provider.Google));
    return await authResultToUser(authResult, Provider.Google);
  }

Another portion of the code is called during app startup

  Future<User> getCurrentUser() async {
    final SharedPreferences pref = await SharedPreferences.getInstance();
    if (pref != null) {
      AuthCredential authCredential;
      String provider = pref.getString("provider");
      Provider providerEnum;
      if (provider != null) {
        if (provider == describeEnum(Provider.Google)) {
          authCredential = GoogleAuthProvider.getCredential(
              idToken: pref.getString("idToken"),
              accessToken: pref.getString("accessToken"));
          providerEnum = Provider.Google;
        } else if (provider == describeEnum(Provider.Facebook)) {
          authCredential = FacebookAuthProvider.getCredential(
              accessToken: pref.getString("accessToken"));
          providerEnum = Provider.Facebook;
        }
        final AuthResult authResult =
            await _auth.signInWithCredential(authCredential);
        return await authResultToUser(authResult, providerEnum);
      }
    }
    return null;
  }

However I am getting error during _auth.signInWithCredential(authCredential), the error is

`ERROR_INVALID_CREDENTIAL` - If the credential data is malformed or has expired.

Looks like what I stored in the SharedPreferences are wrong. Any idea how to fix this ?

Upvotes: 0

Views: 242

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598740

The idea is here to keep the user logged in even after the user has closed the app and relaunch it at much later time.

Firebase already keeps the user signed in, and automatically tries to restore their session without you needing to write any code for it.

But since this may require a call to the server, you may be reading _auth.currentUser before that process has completed. To detect the authentication state properly, use a listener to authStateChanges as shown in the documentation:

FirebaseAuth.instance
  .authStateChanges()
  .listen((User user) {
    if (user == null) {
      print('User is currently signed out!');
    } else {
      print('User is signed in!');
    }
  });

Upvotes: 1

Related Questions