In this tutorial, we’ll learn how to properly implement Flutter Firebase email authentication which includes login, signup, and logout.
Everything from building user interfaces to functions used to send and receive data from Firebase will be practically covered in this tutorial.
Introduction: Flutter Firebase Email Authentication
We’ll be implementing email and password authentication in our Flutter app using Firebase. The concepts we will cover in this tutorial are listed below:
Register – Register a new user in Firebase.
Login – Login/authenticate a user using email and password and navigate him/her to the home screen.
Signout – Logout the user from the home screen and navigate him/her to the login screen.
So let’s start creating it without any more delay.
Implementing Firebase Email and Password Authentication in Flutter App (Step By Step)
Follow the below steps in order to properly understand the implementation of Flutter Firebase email authentication.
Step 1: Setup Firebase
We’ve written a detailed article on how to properly set up Firebase and connect it to your Flutter project.
Click here to perform the Firebase setup process.
Only follow the first step which is titled ‘Step 1: Setup Firebase’. Then come here again to complete the setup process for authentication using Firebase.
Import Firebase Auth Package
firebase_auth: ^4.2.5
Import this package in the dependencies section of your Flutter project’s pubspec.yaml file shown in the below image. Click here to get the latest version of Firebase auth.
import 'package:firebase_auth/firebase_auth.dart';
Use this line in the file where you want to specify the firebase operations. In our case, we’ve specified everything in the main.dart file so we’ve used this import statement inside it.
Step 2: Initialize Firebase
import 'package:firebase_core/firebase_core.dart';
Future main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(const MyApp()); }
Step 3: Activate Email Sign In Authentication
For that, open your Firebase project and click on authentication. Then click on get started and choose email/password. Enable it and click on save as shown in the below image.
Step 4: Creating UI (Login, Register, Home)
The source code will be provided at the end of this article. In the meantime, let’s look at the screens.
Screen 1: Login
This UI has an email and password Flutter textfield and is used to fetch and store data from users. Also, it has a Flutter material button which is used to validate data entered by the user.
If the user enters an email that is not registered, then a Flutter snack bar widget will appear which will show a custom text. Else, the user will be navigated to the home screen.
Also, a Flutter circular progress indicator widget will be shown during the validation process. See the above images for visualization.
We’ve created a custom toggle that is used to show the login or registration screen. Click on it and it’ll show the registration screen if the current one is login and vice versa.
Screen 2: Register
It’s used to register a new user in Firebase using email and password. It’ll check if the current email entered by the user is already present then it’ll display a snack bar. If not, then it’ll navigate the user to the home screen.
Screen 3: Home with Logout Button
This screen will show the email address of the logged-in user. We’ve displayed the email address using the Flutter text widget. Also, we’ve decorated it using a Flutter container widget to make it look less boring.
The sign-out button in the actions section of the Flutter app bar widget is used to log out the user. We’ve used stream which will continuously check the state of the user. If it’s logged out then it’ll show the login screen. If not, then it’ll display on the home screen.
If we close the app and reopen it, then if the user was logged in then it’ll show the home screen. If logged out, then it’ll show the login screen.
Step 5: Firebase Operations
We’ve created a simple class and inside it, we’ve specified the Firebase operations. First, we’ve created an instance of the Firebase auth class. See below:
final FirebaseAuth auth = FirebaseAuth.instance;
1. Login User
Future<void> signIn(email, password) async { await auth.signInWithEmailAndPassword(email: email, password: password); }
2. Register User
Future<void> register(email, password) async { await auth.createUserWithEmailAndPassword(email: email, password: password); }
This method is used to register a new user using email and password if the same email is not registered yet.
3. Sign out User
Future<void> signOut() async { await auth.signOut(); }
It’s used to log out the current(logged-in) user.
Step 6: Auth Status and Stream
Stream<User?> get authStateChanges => auth.authStateChanges();
It’s used to check the status of whether the user is logged in or logged out.
StreamBuilder( stream: AuthClass().authStateChanges, builder: (context, snapshot) { if (snapshot.hasData) { return HomeScreen(); } else { return LoginAndRegisterScreen(); } }, )
Step 7: Current User Data
User? get currentUser => auth.currentUser; // inside Auth class
Text( //display logged in user email address user!.email!.isEmpty ? 'No data' : user!.email.toString() )
So this is how we can easily create Flutter Firebase email authentication. Hope you’ve learned a lot from this tutorial. Do feel free to share it with our Flutter programmers.
Click here to learn how to create a Flutter CRUD app using Firestore.
The complete source code of this whole program of email authentication using Flutter firebase is provided in the below section.
Source Code of Flutter Firebase Email Authentication Program
import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter Firebase Email Authentication App', home: ChooseScreen()); } } class ChooseScreen extends StatelessWidget { const ChooseScreen({super.key}); @override Widget build(BuildContext context) { return StreamBuilder( stream: AuthClass().authStateChanges, builder: (context, snapshot) { if (snapshot.hasData) { return HomeScreen(); } else { return LoginAndRegisterScreen(); } }, ); } } class LoginAndRegisterScreen extends StatefulWidget { const LoginAndRegisterScreen({super.key}); @override State<LoginAndRegisterScreen> createState() => _LoginAndRegisterScreenState(); } class _LoginAndRegisterScreenState extends State<LoginAndRegisterScreen> { bool loginScreenVisible = true; bool showLoading = false; String email = ''; String password = ''; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( centerTitle: true, title: Text(loginScreenVisible ? 'Login' : 'Signup'), backgroundColor: Colors.purple, ), body: SingleChildScrollView( padding: EdgeInsets.symmetric(horizontal: 50, vertical: 200), child: Column( children: [ inputField('email'), inputField('password'), !loginScreenVisible ? SizedBox() : forgotPassword(), loginRegisterButton(), toggleIconButton() ], ), ), ); } /// Flutter textfield /// Widget inputField(fieldType) { return Padding( padding: EdgeInsets.only(bottom: 10), child: TextField( onChanged: (value) { setState(() { if (fieldType == 'email') { email = value; } if (fieldType == 'password') { password = value; } }); }, cursorColor: Colors.purple.shade400, decoration: InputDecoration( focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.purple.shade400)), hintText: fieldType == 'email' ? 'Enter email...' : 'Enter password...', hintStyle: TextStyle(color: Colors.grey.shade400, fontSize: 14)), ), ); } /// Forgot password /// Widget forgotPassword() { return Align( alignment: Alignment.centerRight, child: Text( 'Forgot password?', style: TextStyle( color: Colors.black54, fontWeight: FontWeight.w500, fontSize: 13), )); } /// Login and Register Button Widget loginRegisterButton() { return Padding( padding: EdgeInsets.only(top: 31, bottom: 21), child: MaterialButton( onPressed: email.isEmpty || password.isEmpty ? null : () async { setState(() {}); showLoading = true; if (loginScreenVisible) { try { print('get it now'); await AuthClass().signIn(email, password); print('get it'); } on FirebaseAuthException catch (e) { if (AuthClass().currentUser == null) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text('Invalid email or password'))); } } setState(() { showLoading = false; }); } if (!loginScreenVisible) { try { await AuthClass().register(email, password); } on FirebaseAuthException catch (e) { var res = await AuthClass() .auth .fetchSignInMethodsForEmail(email); if (res.isNotEmpty) ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('User already exists'))); } setState(() { showLoading = false; }); } }, padding: EdgeInsets.symmetric(vertical: 13), minWidth: double.infinity, color: Colors.purple.shade300, disabledColor: Colors.grey.shade300, textColor: Colors.white, child: showLoading ? SizedBox( height: 20, width: 20, child: CircularProgressIndicator( color: Colors.white, ), ) : Text(loginScreenVisible ? 'Login' : 'Register')), ); } /// custom toggle button /// Widget toggleIconButton() { return InkWell( onTap: () { setState(() { loginScreenVisible = !loginScreenVisible; }); }, child: Container( padding: EdgeInsets.all(5), height: 50, width: 100, decoration: BoxDecoration( color: Colors.purple.shade100, borderRadius: BorderRadius.circular(100)), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ loginScreenVisible ? toggleButtonText() : Expanded( child: Center( child: Text( 'Login', style: TextStyle(color: Colors.white, fontSize: 11), ), ), ), !loginScreenVisible ? toggleButtonText() : Expanded( child: Center( child: Text( 'Signup', style: TextStyle(color: Colors.white, fontSize: 11), ), ), ), ], ), ), ); } Widget toggleButtonText() { return Expanded( child: Container( alignment: Alignment.center, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.purple.shade300), child: Text( loginScreenVisible ? 'Login' : 'Signup', style: TextStyle(color: Colors.white, fontSize: 11), ), ), ); } } //// home screen /// class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State<HomeScreen> createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { final User? user = AuthClass().currentUser; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.purple, centerTitle: true, title: Text('Home Screen'), actions: [ MaterialButton( onPressed: () async { await AuthClass().signOut(); }, child: Text('Signout', style: TextStyle(color: Colors.white))) ], ), body: Center( child: Container( padding: EdgeInsets.all(11), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( blurRadius: 3, spreadRadius: 1, offset: Offset(3, 3), color: Colors.grey.shade200) ]), child: Text( user!.email!.isEmpty ? 'No data' : user!.email.toString())), ), ); } } /// Firebase Operations /// class AuthClass { final FirebaseAuth auth = FirebaseAuth.instance; User? get currentUser => auth.currentUser; Stream<User?> get authStateChanges => auth.authStateChanges(); Future<void> signIn(email, password) async { await auth.signInWithEmailAndPassword(email: email, password: password); } Future<void> register(email, password) async { await auth.createUserWithEmailAndPassword(email: email, password: password); } Future<void> signOut() async { await auth.signOut(); } }
Conclusion
In conclusion, so this is how we can practically implement Flutter Firebase email authentication. Do feel free to share your valuable feedback in the comment section or email us. We’d love to read it.
We’d also love to see you visit our other tutorials on Flutter app development. Thank you for reading this one.