'how do I verify a new user's email in Flutter and Firebase before granting them access to the app?

I am trying to have new users create an account, receive a verification email and then only be granted access to the app once they have clicked the verification link sent by Firebase. I am not getting any errors but there are clearly shortcomings in my code. The new user information is accepted and stored by Firestore and a verification email is sent but once the verification link is clicked the user remains on the Verify page instead of navigating to the HomePage (called Jobs Page in this code).

I cannot figure this out after days of trying so any help would be greatly appreciated. I have included several pages of my code. Thanks in advance!

abstract class AuthBase {
  User? get currentUser;
  Stream<User?> authStateChanges();

  Future<User?> signInWithEmailAndPassword(String email, String password);
  Future<void> createUserWithEmailAndPasswordVerify(
      String email, String password);
  Future<void> signOut();
}

class Auth implements AuthBase {
  // Value that retrieves an instance of the FirebaseAuth object. This is used for managing users between the app and the Firebase backend
  final _firebaseAuth = FirebaseAuth.instance;

  @override
  Stream<User?> authStateChanges() => _firebaseAuth.authStateChanges();

  @override
  User? get currentUser => _firebaseAuth.currentUser;

  @override
  Future<User?> signInWithEmailAndPassword(
      String email, String password) async {
    final userCredential = await _firebaseAuth.signInWithCredential(
      EmailAuthProvider.credential(
        email: email,
        password: password,
      ),
    );
    return userCredential.user;
  }

  @override
  Future<User?> createUserWithEmailAndPasswordVerify(
      String email, String password) async {
    final userCredential = await _firebaseAuth.createUserWithEmailAndPassword(
      email: email,
      password: password,
    );
    try {
      await userCredential.user?.sendEmailVerification();
    } catch (e) {
      print(
        'An error occurred while trying to send email verification',
      );
    }
    return userCredential.user;
  }

  @override
  Future<void> signOut() async {
    await GoogleSignIn().signOut();
    await _firebaseAuth.signOut();
  }
}


class VerifyPage extends StatefulWidget {
  const VerifyPage({
    Key? key,
  }) : super(key: key);

  @override
  State<VerifyPage> createState() => _VerifyPageState();
}

class _VerifyPageState extends State<VerifyPage> {
  AuthBase? auth;
  Timer? timer;
  User? user;
  bool isUserEmailVerified = false;

  @override
  void initState() {
    super.initState();
    user = auth?.currentUser;
    user?.sendEmailVerification();
    timer = Timer.periodic(
      const Duration(
        seconds: 5,
      ),
      (timer) {
        checkEmailVerified();
      },
    );
  }

  Future<void> checkEmailVerified() async {
    user = auth?.currentUser;
    await user?.reload();
    final signedInUser = user;
    if (signedInUser != null && signedInUser.emailVerified) {
      timer?.cancel();
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(
          builder: (context) => const JobsPage(),
        ),
      );
    }
  }

  @override
  void dispose() {
    timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: Container(),
        title: const Text('Verify Email'),
      ),
      body: const Center(
        child: Padding(
          padding: EdgeInsets.all(16.0),
          child: Text(
            'An email has just been sent to your email.  Click on the link provided to complete registration.',
            style: TextStyle(
              fontSize: 20.0,
            ),
          ),
        ),
      ),
    );
  }
}

code from email sign in form

Future<void> _submitVerify() async {
    try {
      await model.submitVerify(context);
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(
          builder: (context) => const VerifyPage(),
        ),
      );
    } on FirebaseAuthException catch (e) {
      showExceptionAlertDialog(
        context,
        exception: e,
        title: 'Sign In Failed',
      );
    }
  }


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source