Home > Software engineering >  Firebase Auth login and logout based on user's account status
Firebase Auth login and logout based on user's account status

Time:04-28

I am making an application. I made an account system for the application. But I want to ask something. I separated the login screen and the normal application screens. If the user's account is not open, the login screen; If it is open, it is redirected to the application.

I wrote the following code for this:

main.dart:

import 'package:flutter/material.dart';
import 'package:simto_todolist/app.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:simto_todolist/welcome_splashs.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}
  var user = FirebaseAuth.instance.currentUser;

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: accountState(),
    );
  }
}

accountState() {
  if (user == null) {
    return splashScreen(); // login
  } else {
    return app(); // app
  }
}

I also put a logout button in my application. Pressing this button exits the application, but the application just freezes. So the app doesn't know what to do. Then I start the application from the beginning, it redirects to the login screen.

I believe this problem will be solved if I can constantly check that the user's account is open. How can I do this what I want?

The code I gave above only checks once, when the application starts. I want him to check it all the time.


After doing what Peter Koltai said, main.dart:

import 'package:flutter/material.dart';
import 'package:simto_todolist/app.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:simto_todolist/welcome_splashs.dart';
import 'package:provider/provider.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}
  var user = FirebaseAuth.instance.currentUser;

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<AuthState>(
        create: (context) => AuthState()),
      ],
      builder: (context, child) {
        return MaterialApp(
          home: context.watch<AuthState>().user == null ? 
          splashScreen() : app(),
        );
      }
    );
  }
}

class AuthState with ChangeNotifier {
  User _user;
  User get user => _user;
  set user(User currentUser) {
    _user = currentUser;
    notifyListeners();
  }
  MyAuthState() {   
    FirebaseAuth.instance.authStateChanges().listen((User currentUser) {
      user = currentUser;
    });
  }
}

The screen does not change when the user logs in in splashScreen().


Login codes:

  RaisedButton(
    child: Padding(
      padding: const EdgeInsets.only(right: 85, left: 85, top: 12, bottom: 12),
        child: Text("Login", style: TextStyle(color: Colors.white, fontSize: 20, fontFamily: "Roboto-Thin"),),
    ),
    color: Colors.blue[400],
    textColor: Colors.white,
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(30.0),
    ),
    onPressed: () async {
      if (_loginEmail.text.isEmpty || _loginPassword.text.isEmpty) {
        CoolAlert.show(
          context: context,
          type: CoolAlertType.error,
          title: "Error",
          text: "Please fill in all fields completely."
        );
      }
      else if(validateEmail (_loginEmail.text) != null) {
        CoolAlert.show(
          context: context,
          type: CoolAlertType.error,
          title: "Error",
          text: validateEmail (_loginEmail.text)
        );
      }
      else {
        try {
          await FirebaseAuth.instance.signInWithEmailAndPassword(
            email: _loginEmail.text,
            password: _loginPassword.text,
          );
      } on FirebaseAuthException catch (e) {
          if (e.code == 'user-not-found') {
            CoolAlert.show(
              context: context,
              type: CoolAlertType.error,
              title: "Error",
              text: "No such user was found."
            );
          }
          else if (e.code == 'wrong-password') {
            CoolAlert.show(
              context: context,
              type: CoolAlertType.error,
              title: "Error",
              text: "Password is incorrect."
            );
          }
          else {
            CoolAlert.show(
              context: context,
              type: CoolAlertType.error,
              title: "Error",
              text: "An unknown error has occurred. Please try again later."
            );
          }
        }
      }
    },
  ),

CodePudding user response:

First set up a listener to authentication state changes like:

FirebaseAuth.instance.authStateChanges().listen((User? user) {
  // execute any logic depending on current authentication state
});

This will be called when user is logged in or out. The next step is to update you application's home route based on this change. One possible solution is to use provider for state management, check here.

Create a class in main.dart for the provider:

class AuthState with ChangeNotifier {
  User? _user;
  User? get user => _user;
  set user(User? currentUser) {
    _user = currentUser;
    notifyListeners();
  }
  MyAuthState() {   
    FirebaseAuth.instance.authStateChanges().listen((User? currentUser) {
      user = currentUser;
    });
  }
}

Don't forget to add provider package and import it into main.dart.

After this you can create your MaterialApp like this (you don't really need MultiProvider but later if you add more providers it can be useful):

return MultiProvider(
  providers: [
    ChangeNotifierProvider<AuthState>(
      create: (context) => AuthState()),
  ],
  builder: (context, child) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: context.watch<AuthState>().user == null ? 
        splashScreen() : app(),
    );
  });
  • Related