Flutter Firebase Authentication Tutorial 2022 using GETX

Basics, Database, Flutter Firebase, Flutter Login App

In this flutter tutorial, we will learn flutter firebase authentication. Using Email and Password, we will use GETX State Management to perform firebase authentication in a flutter.

  • There will be many topics that we will cover in this playlist and they are as follows.
  • Create a user with an email and password
  • Sign In user with email and password
  • Logout the user
  • Keep the firebase user logged in even app closed
  • Keep the separation of concern with a separate Authentication Repository Controller
  • Signup, and login controller with the backend logic.

Watch Youtube tutorial

 

Step 1: Setup Firebase Authentication

Before directly starting with firebase authentication, you need to have few things up and running.

We are creating Flutter Login App and we have already learned and designed the Login App. You can download the code from here, or watch the playlist here.

Firstly, you have to setup firebase in flutter.

Enable the Email SignIn method in Firebase Console.

Add firebase_auth dependency in the pubspec.ymal file in your flutter project.

Once everything setup, now let’s configure main.dart because whenever our project loads, it should load firebase.

Therefore, we will add WidgetsFlutterBinding.ensureInitialized(); so that our flutter widgets wait until firebase initilization completed and afterwards, we will call the firebase like

Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

 

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

@override
Widget build(BuildContext context) {
final controller = Get.put(SignUpController());
final _formKey = GlobalKey<FormState>();

return Container(
padding: const EdgeInsets.symmetric(vertical: tFormHeight - 10),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: controller.fullName,
decoration: const InputDecoration(label: Text(tFullName), prefixIcon: Icon(Icons.person_outline_rounded)),
),
const SizedBox(height: tFormHeight - 20),
TextFormField(
controller: controller.email,
decoration: const InputDecoration(label: Text(tEmail), prefixIcon: Icon(Icons.email_outlined)),
),
const SizedBox(height: tFormHeight - 20),
TextFormField(
controller: controller.phoneNo,
decoration: const InputDecoration(label: Text(tPhoneNo), prefixIcon: Icon(Icons.numbers)),
),
const SizedBox(height: tFormHeight - 20),
TextFormField(
controller: controller.password,
decoration: const InputDecoration(label: Text(tPassword), prefixIcon: Icon(Icons.fingerprint)),
),
const SizedBox(height: tFormHeight - 10),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
if(_formKey.currentState!.validate()){
SignUpController.instance.registerUser(controller.email.text.trim(), controller.password.text.trim());
}
},
child: Text(tSignup.toUpperCase()),
),
)
],
),
),
);
}
}

import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../../../repository/authentication_repository/authentication_repository.dart';

class SignUpController extends GetxController {
  static SignUpController get instance => Get.find();

  //TextField Controllers to get data from TextFields
  final email = TextEditingController();
  final password = TextEditingController();
  final fullName = TextEditingController();
  final phoneNo = TextEditingController();

  //Call this Function from Design & it will do the rest
  void registerUser(String email, String password) {
    String? error = AuthenticationRepository.instance.createUserWithEmailAndPassword(email, password) as String?;
    if(error != null) {
      Get.showSnackbar(GetSnackBar(message: error.toString(),));
    }
  }

}
import 'package:firebase_auth/firebase_auth.dart';
import 'package:get/get.dart';
import 'package:login_flutter_app/src/features/authentication/screens/welcome/welcome_screen.dart';
import 'package:login_flutter_app/src/features/core/screens/dashboard/dashboard.dart';

import 'exceptions/login_with_email_and_pssword_failure.dart';
import 'exceptions/signup_email_password_failure.dart';

class AuthenticationRepository extends GetxController {
static AuthenticationRepository get instance => Get.find();

//Variables
final _auth = FirebaseAuth.instance;
late final Rx<User?> firebaseUser;

//Will be load when app launches this func will be called and set the firebaseUser state
@override
void onReady() {
firebaseUser = Rx<User?>(_auth.currentUser);
firebaseUser.bindStream(_auth.userChanges());
ever(firebaseUser, _setInitialScreen);
}

/// If we are setting initial screen from here
/// then in the main.dart => App() add CircularProgressIndicator()
_setInitialScreen(User? user) {
user == null ? Get.offAll(() => const WelcomeScreen()) : Get.offAll(() => const Dashboard());
}

//FUNC
Future<String?> createUserWithEmailAndPassword(String email, String password) async {
try {
await _auth.createUserWithEmailAndPassword(email: email, password: password);
firebaseUser.value != null ? Get.offAll(() => const Dashboard()) : Get.to(() => const WelcomeScreen());
} on FirebaseAuthException catch (e) {
final ex = SignUpWithEmailAndPasswordFailure.code(e.code);
return ex.message;
} catch (_) {
const ex = SignUpWithEmailAndPasswordFailure();
return ex.message;
}
return null;
}

Future<String?> loginWithEmailAndPassword(String email, String password) async {
try {
await _auth.signInWithEmailAndPassword(email: email, password: password);
} on FirebaseAuthException catch (e) {
final ex = LogInWithEmailAndPasswordFailure.fromCode(e.code);
return ex.message;
} catch (_) {
const ex = LogInWithEmailAndPasswordFailure();
return ex.message;
}
return null;
}

Future<void> logout() async => await _auth.signOut();
}

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:login_flutter_app/src/common_widgets/form/form_header_widget.dart';
import 'package:login_flutter_app/src/common_widgets/form/social_footer.dart';
import 'package:login_flutter_app/src/constants/image_strings.dart';
import 'package:login_flutter_app/src/constants/text_strings.dart';
import 'package:login_flutter_app/src/features/authentication/screens/signup/signup_screen.dart';
import '../../../../common_widgets/form/form_divider_widget.dart';
import '../../../../constants/sizes.dart';
import 'widgets/login_form_widget.dart';

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

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: SingleChildScrollView(
          child: Container(
            padding: const EdgeInsets.all(tDefaultSpace),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const FormHeaderWidget(image: tWelcomeScreenImage, title: tLoginTitle, subTitle: tLoginSubTitle),
                const LoginFormWidget(),
                const TFormDividerWidget(),
                SocialFooter(text1: tDontHaveAnAccount, text2: tSignup, onPressed: () => Get.off(() => const SignupScreen())),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:line_awesome_flutter/line_awesome_flutter.dart';
import 'package:login_flutter_app/src/common_widgets/buttons/primary_button.dart';
import 'package:login_flutter_app/src/features/authentication/controllers/login_controller.dart';
import '../../../../../constants/sizes.dart';
import '../../../../../constants/text_strings.dart';
import '../../../../../utils/helper/helper_controller.dart';
import '../../forget_password/forget_password_options/forget_password_model_bottom_sheet.dart';

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

  @override
  Widget build(BuildContext context) {
    final controller = Get.put(LoginController());
    return Container(
      padding: const EdgeInsets.symmetric(vertical: tFormHeight),
      child: Form(
        key: controller.loginFormKey,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            /// -- Email Field
            TextFormField(
              validator: Helper.validateEmail,
              controller: controller.email,
              decoration:
                  const InputDecoration(prefixIcon: Icon(LineAwesomeIcons.user), labelText: tEmail, hintText: tEmail),
            ),
            const SizedBox(height: tFormHeight - 20),

            /// -- Password Field
            Obx(
              () => TextFormField(
                controller: controller.password,
                validator: (value) {
                  if (value!.isEmpty) return 'Enter your password';
                  return null;
                },
                obscureText: controller.showPassword.value ? false : true,
                decoration: InputDecoration(
                  prefixIcon: const Icon(Icons.fingerprint),
                  labelText: tPassword,
                  hintText: tPassword,
                  suffixIcon: IconButton(
                    icon: controller.showPassword.value
                        ? const Icon(LineAwesomeIcons.eye)
                        : const Icon(LineAwesomeIcons.eye_slash),
                    onPressed: () => controller.showPassword.value = !controller.showPassword.value,
                  ),
                ),
              ),
            ),
            const SizedBox(height: tFormHeight - 20),

            /// -- FORGET PASSWORD BTN
            Align(
              alignment: Alignment.centerRight,
              child: TextButton(
                onPressed: () => ForgetPasswordScreen.buildShowModalBottomSheet(context),
                child: const Text(tForgetPassword),
              ),
            ),

            /// -- LOGIN BTN
            Obx(
              () => TPrimaryButton(
                isLoading: controller.isLoading.value ? true : false,
                text: tLogin.tr,
                onPressed: controller.isFacebookLoading.value || controller.isGoogleLoading.value
                    ? () {}
                    : controller.isLoading.value
                        ? () {}
                        : () => controller.login(),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
import 'package:flutter/material.dart';

class FormHeaderWidget extends StatelessWidget {
const FormHeaderWidget({
Key? key,
this.imageColor,
this.heightBetween,
required this.image,
required this.title,
required this.subTitle,
this.imageHeight = 0.15,
this.textAlign,
this.crossAxisAlignment = CrossAxisAlignment.start,
}) : super(key: key);

//Variables -- Declared in Constructor
final Color? imageColor;
final double imageHeight;
final double? heightBetween;
final String image, title, subTitle;
final CrossAxisAlignment crossAxisAlignment;
final TextAlign? textAlign;

@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;

return Column(
crossAxisAlignment: crossAxisAlignment,
children: [
Image(image: AssetImage(image), color: imageColor, height: size.height * imageHeight),
SizedBox(height: heightBetween),
Text(title, style: Theme.of(context).textTheme.displayLarge),
Text(subTitle, textAlign: textAlign, style: Theme.of(context).textTheme.bodyLarge),
],
);
}
}
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../../../repository/authentication_repository/authentication_repository.dart';

class LoginController extends GetxController {
  static LoginController get instance => Get.find();

  /// TextField Controllers to get data from TextFields
  final email = TextEditingController();
  final password = TextEditingController();

  /// TextField Validation

  //Call this Function from Design & it will do the rest
  Future<void> login() async {
    String? error = await AuthenticationRepository.instance.loginWithEmailAndPassword(email.text.trim(), password.text.trim());
    if(error != null) {
      Get.showSnackbar(GetSnackBar(message: error.toString(),));
    }

  }
}

6 – Clean Code

So far we were creating everything inside dashboard.dart but at the end you will see our code size has increased alot and become unmanageable.

Therefore, we have to convert our code into separate Custom widgets.

CODING with T

🚀 Supercharge your Flutter skills! Subscribe to my YouTube channel now for mind-blowing coding insights, expert tips, and exclusive content. Don’t miss out!

Best Laptops for Developers 2024 Top Picks & Reviews

Source code

COURSES

Flutter E Commerce App Modern and latest
Flutter Login App UI Source Code - Flutter Complete App - Flutter App Design - Flutter App 2023 - Complete Flutter App 2023
Learn flutter from scratch in 4 hours - Flutter Crash Course - Coding with T

Learn Flutter

1.2 # How to install flutter on android studio 2022 - Flutter Basic Crash Course
2.2 - Add Image in Flutter - Assets Network- Flutter Basic Crash Course 2022

flutter Design

How to create a Custom Shape in Flutter. Flutter E Commerce app Design. Ecommerce app design Flutter. Flutter clippath tutorial
How to create a Custom Appbar in flutter. Custom Appbar Design. Flutter App Design
16 - Product Card and Grid Layout, How to create a Grid View in Flutter. How to add Products in GridView Layout. Flutter eCommerce app UI Design
Bottom Navigation bar in Flutter. Flutter Material 3 bottom navigation bar. How to design background color of Flutter bottom navigation bar. Flutter ecommerce app design
23 - Product Detail Screen, How to create Products Details Screen in Flutter. Flutter eCommerce app UI Design

Flutter Backend

33 - How to Setup Firebase - Firebase Basics - Flutter Firebase - Flutter ecommerce app with firebase as backend
38 - How to Sign-in with Google in flutter Firebase, Firebase Basics, Flutter Firebase, Flutter ecommerce app with firebase as backend
40 - Flutter Firebase CRUD,  Firebase Basics, Flutter Firebase, Flutter ecommerce app with firebase as backend
Are you looking for a Laptop? Checkout the Best Laptops for Programming.
This is default text for notification bar