skip to Main Content

I’m using Firebase and Provider on my SignIn/Signup part of my mobile app.
Please take a look at the snipets to get a better idea.

main.dart

  @override
  Widget build(BuildContext context) {
   return MultiProvider(
     providers: [
       Provider<FirebaseBridge>(
         create: (_) => FirebaseBridge(),),
           StreamProvider(
             create: (context) =>
               context.read<FirebaseBridge>().monitorAuthStateChanges,
                 initialData: null),
     ],
     child: MaterialApp(
     home: const SplashScreen(),
    ...
  ),);}

Splash redirects to AuthCheck.

auth_check.dart

    class AuthCheck extends StatelessWidget {
      const AuthCheck({Key? key}) : super(key: key);
      @override
      Widget build(BuildContext context) {
        final userModel = Provider.of<UserModel?>(context);
        if (userModel == null) {
          return const WelcomeScreen();
        } else {
          return const Home();
}}}

Welcome has buttons to SignIn and SignUp.
SignIn calls FirebaseAuth signInUserWithEmailAndPassword and everything works fine.

SignIn Screen

  void doLogIn(String email, String password) {
context
    .read<FirebaseBridge>()
    .logIn(
      emailController.text.trim(),
      passwordController.text.trim())
    .then(
  (value) {
    Navigator.pushReplacement(
        context, MaterialPageRoute(builder: (_) => const Home()));
    emailController.clear();
    passwordController.clear();
  },
  onError: (error) {
    DialogBoxes.showErrorBox(context,
        message:
            'Ops! Some message and show the n($error)');
  },
);

}

And the class that interacts with Firebase.

class FirebaseBridge {
  final FirebaseAuth _fireAuth = FirebaseAuth.instance;
  Stream<UserModel?> get monitorAuthStateChanges {
    return _fireAuth.authStateChanges().map(_userModelFromFirebase);
  }
  UserModel? _userModelFromFirebase(User? user) {
    if (user != null) {
      return UserModel(uid: user.uid);
    } else {
      return null;
    }
  }
  Future<void> logIn(String pEmail, String pPassword) async {
    try {
      await _fireAuth.signInWithEmailAndPassword(
        email: pEmail, password: pPassword);
    } on FirebaseAuthException catch (e) {
      final ex = AuthExceptions.code(e.code);
      return Future.error('${ex.message} - ${e.code}');
    } on SocketException catch (e) {
      return Future.error('Web Socketn($e)n(${e.osError})');
    } on PlatformException catch (e) {
      return Future.error('Platformn($e)n(${e.message})');
    } catch (e) {
      return Future.error('Unexpectedn($e)n(${e.toString()})');
    }
  }

My question is: Do I have to check if the user is logged in on everyscreen of the app? let’s say at the top of every screen call some method and ask Provider if the user is still logged in? Any comments on this or about the code would be really appreciated.
Thanks.

2

Answers


  1. My strategy is to have a high-level widget (very close to my main(runApp...) watch the authchanges stream, and select a subwidget for either "logged in" or "logged out". Within each widget, I then start my MaterialApp (holding a router) and various Scaffolds below that.

    This way, I’m guaranteed to only be in half of my app at a time… the parts that work while I’m logged out, and the parts that work while I’m logged in. Even if I screw up routing, I won’t end up in disallowed pages.

    Login or Signup to reply.
  2. Create a stream of User getAuthChanges in FirebaseAuthClass:

    Stream<User?> get getAuthChanges => _auth.authStateChanges();
    

    Return a StreamBuilder in auth_check.dart:

    return StreamBuilder(
              stream: FirebaseAuthClass().getAuthChanges,
              builder: (context, snapshot) {
                if(snapshot.hasData){
                  return const HomePage();
                }else{
                  return const SignInPage();
                }
              },
            );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search