0

I have the following code and I need to keep users logged when they reopen the app. I have a flutter phone authentication service from firebase. The given is function to verify google phone authentication. There is a button when pressed 2 functions mentioned below to get call named verifyPhoneNumber() & signInWithPhoneNumber().

void verifyPhoneNumber() async {
if (_formKey.currentState!.validate()) {
  setState(() {
    loading = true;
  });
  PhoneVerificationCompleted verificationCompleted =
      (PhoneAuthCredential phoneAuthCredential) async {
    User? user;
    bool error = false;
    try {
      user = (await firebaseAuth.signInWithCredential(phoneAuthCredential))
          .user!;
    } catch (e) {
      print("Failed to sign in: " + e.toString());
      error = true;
    }
    if (!error && user != null) {
      String id = user.uid;
      //here you can store user data in backend
      Navigator.pushReplacement(
          context,
          MaterialPageRoute(
              builder: (context) => PhoneAuthDataNext(
                    phone: phoneNumber,
                  )));
    }
  };

  PhoneVerificationFailed verificationFailed =
      (FirebaseAuthException authException) {
    showToast(authException.message!);
  };
  PhoneCodeSent codeSent =
      (String? verificationId, [int? forceResendingToken]) async {
    showToast('Please check your phone for the verification code.');
    this.forceResendingToken = forceResendingToken;
    _verificationId = verificationId;
  };
  PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
      (String verificationId) {
    _verificationId = verificationId;
  };
  try {
    await firebaseAuth.verifyPhoneNumber(
        phoneNumber: phoneNumber!,
        timeout: const Duration(seconds: 10),
        forceResendingToken:
            forceResendingToken != null ? forceResendingToken : null,
        verificationCompleted: verificationCompleted,
        verificationFailed: verificationFailed,
        codeSent: codeSent,
        codeAutoRetrievalTimeout: codeAutoRetrievalTimeout);
    showOtpScreen = true;
  } catch (e) {
    showToast("Failed to Verify Phone Number: $e");
    showOtpScreen = false;
  }
  setState(() {
    loading = false;
  });
}

}

void signInWithPhoneNumber() async {
    bool error = false;
    User? user;
    AuthCredential credential;
    setState(() {
      loading = true;
    });
    try {
      credential = PhoneAuthProvider.credential(
        verificationId: _verificationId!,
        smsCode: otpEditingController.text,
      );
      user = (await firebaseAuth.signInWithCredential(credential)).user!;
    } catch (e) {
      showToast("Failed to sign in: " + e.toString());
      error = true;
    }
    if (!error && user != null) {
      credential = PhoneAuthProvider.credential(
        verificationId: _verificationId!,
        smsCode: otpEditingController.text,
      );
      UserCredential userCredential =
          await firebaseAuth.signInWithCredential(credential);
      storeTokenAndData(userCredential);

      //here you can store user data in backend
      Navigator.pushReplacement(
          context,
          MaterialPageRoute(
              builder: (context) => PhoneAuthDataNext(
                    phone: phoneNumber,
                    credential: credential,
                  )));
    }
    setState(() {
      loading = false;
    });
  }

Please Give me a solution.

JideGuru
  • 7,102
  • 6
  • 26
  • 48

2 Answers2

0

Firebase already restores the user credentials from local storage/shared preferences when the app restarts. But this is an asynchronous process, since it requires a call to the server.

To detect and respond to the authentication state, listen to the authStateChanges stream as shown in the documentation on authentication state.

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

You'll typically want to wrap FirebaseAuth.instance.authStateChanges() in a StreamBuilder to show the correct UI state based on whether the user is signed in.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
0

Firebase already handles the 'session' for you. You can use the authStateChanges method to check auth state and update your UI as I have done with the code below

class AuthGate extends StatelessWidget {
  const AuthGate({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (BuildContext context, AsyncSnapshot<User?> snapshot) {
        if (snapshot.hasData) {
          return HomePage();
        }
        return LoginPage();
      },
    );
  }
}
JideGuru
  • 7,102
  • 6
  • 26
  • 48