Firebase Integration and Creating Basic Firebase Login SignUp Authentication in Flutter
In this article, I will explain how to integrate Firebase and create basic login and sign-up screens in Flutter. This article will consist of two parts. The first part will provide a detailed explanation of how to integrate Firebase, while the second part will assist you in creating login and sign-up screens.
Setting Up the Project
Open a new terminal. Navigate to the directory where you want to create a new Flutter project using terminal commands. Then, use the following command to create a new Flutter project:
flutter create example_project
You can replace “example_project” with the name of the project you want to create. In my case project name is firebaseauth.
Firebase Integration
●Step 1: For Firebase integration, you will need to use the “pub” commands, so please make sure to add the “bin” folder inside the “pub” folder to your PATH if you haven’t done so already. You can refer to the image below for guidance, but keep in mind that the location of the “pub” folder may vary, so you’ll need to locate it yourself. This will allow you to run the “pub” commands.
●Step 2: Download and install Node.js using the following link.
●Step 3: Create a Firebase project using the link below.
●Step 4: Download the CLI using the link below.
https://firebase.google.com/docs/cli
●Step 5: Follow the steps in the image below to install the CLI.
⚠️ Warning: After seeing the ‘Success!’ message, please do not close this window.
●Step 6: Copy the code I’ve added below and paste it into the window we left open in the previous step, following the instructions in the image below. You can find the code on this link: https://firebase.flutter.dev/docs/cli/
dart pub global activate flutterfire_cli
●Step 7: Open your project that you initially created using the “flutter create” command. Make sure you have your terminal open and are in the project folder, and ensure that you’re using PowerShell (you can see it on the right side). If you don’t see the “PowerShell” option, you can select it by using the “˅” symbol.
●Step 8 Add necessary dependencies:
To define dependencies, first open the pubspec.yaml file, which is located at the bottom of your project. Afterward, add these package under the “dependencies” section. You can find the latest “firebase_core” and “firebase_auth” package at those links.
● firebase_core :
https://pub.dev/packages/firebase_core
● firebase_auth :
https://pub.dev/packages/firebase_auth
dependencies:
flutter:
sdk: flutter
firebase_core: ^latest_version
firebase_auth: ^latest_version
Please make sure to replace “^latest_version” (in my case) with the suitable versions of the packages. You can save the packages by using the Ctrl+S keys. Additionally, you can also install these packages using terminal commands (you can find tutorial guides in the links). The versions I used in this article are as follows: firebase_core: ^2.15.1
, firebase_auth: ^4.9.0
Firebase Login Sign Up Authentication
●Step 1: Add the code below to the main.dart file (located in the lib folder).
import 'package:firebaseauth/login_screen.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: LoginScreen(),
);
}
}
●Step 2: Create a login_screen.dart file inside the lib folder and add the following code to it.
import 'package:firebaseauth/signup_screen.dart';
import 'package:firebaseauth/wellcome.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final FirebaseAuth _auth = FirebaseAuth.instance;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
TextEditingController _emailController = TextEditingController();
TextEditingController _passController = TextEditingController();
String _email = "";
String _password ="";
void _handleLogin() async {
try {
UserCredential userCredential = await _auth.signInWithEmailAndPassword(
email: _email,
password: _password,
);
print("User Logged In: ${userCredential.user!.email}");
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => Welcome(),
),
);
} catch (e) {
String errorMessage = "Invalid email or password.";
print("Error During Logged In: $e");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(errorMessage),
),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Login"),
),
body: Center(
child: Padding(
padding:EdgeInsets.all(16),
child: Form(
key:_formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
controller: _emailController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Email",
),
validator: (value){
if(value== null || value.isEmpty){
return "Please Enter Your Email";
}
return null;
},
onChanged: (value){
setState(() {
_email = value;
});
},
),
SizedBox(height: 20,),
TextFormField(
controller: _passController,
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Password",
),
validator: (value){
if(value== null || value.isEmpty){
return "Please Enter Your Password";
}
return null;
},
onChanged: (value){
setState(() {
_password = value;
});
},
),
Column(
children: [
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_handleLogin();
}
},
child: Text("Login"),
),
SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Don't have an account?"),
TextButton(
onPressed: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => SignUpScreen()),
);
},
child: Text("Sign up"),
),
],
),
],
)
],
),
),
),
),
);
}
}
●Step 3: To create the welcome screen that will be displayed upon successful login, create a “welcome.dart” file inside the “lib” folder and add the following code to it.
import 'package:firebaseauth/login_screen.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class Welcome extends StatefulWidget {
const Welcome({super.key});
@override
State<Welcome> createState() => _WelcomeState();
}
class _WelcomeState extends State<Welcome> {
final FirebaseAuth _auth = FirebaseAuth.instance;
@override
Widget build(BuildContext context) {
String? _email = _auth.currentUser!.email;
return Scaffold(
appBar: AppBar(
title: Text("Dashboard"),
),
body: Center(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Login In With:\n$_email",
style: TextStyle(
fontSize: 30
),),
SizedBox(height: 50,),
ElevatedButton(
onPressed: () {
_auth.signOut();
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => LoginScreen(),
),
);
},
child: Text("Signout"),
)
],
),
),
),
);
}
}
●Step 4: To create the sign-up screen that will be navigated to when users without an account click the “Sign Up” TextButton on the login screen, create a “signup_screen.dart” file inside the “lib” folder and add the following code to it.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'login_screen.dart';
class SignUpScreen extends StatefulWidget {
const SignUpScreen({super.key});
@override
State<SignUpScreen> createState() => _SignUpScreenState();
}
class _SignUpScreenState extends State<SignUpScreen> {
final FirebaseAuth _auth = FirebaseAuth.instance;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
TextEditingController _emailController = TextEditingController();
TextEditingController _passController = TextEditingController();
String _email = "";
String _password = "";
bool _showSuccessMessage = false;
String? _errorMessage;
void _handleSignUp() async {
try {
UserCredential userCredential = await _auth.createUserWithEmailAndPassword(
email: _email,
password: _password,
);
setState(() {
_showSuccessMessage = true;
});
_emailController.clear();
_passController.clear();
print("User Registered: ${userCredential.user!.email}");
} on FirebaseAuthException catch (e) {
setState(() {
_errorMessage = e.message;
});
print("Error During Registration: $e");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sign Up"),
),
body: Center(
child: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_showSuccessMessage
? Column(
children: [
Text(
"Congratulations, your account has been successfully created.",
style: TextStyle(
color: Colors.green,
fontWeight: FontWeight.bold,
),
),
TextButton(
onPressed: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => LoginScreen(),
),
);
},
child: Text("Login"),
),
],
)
: SizedBox(),
SizedBox(height: 10),
TextFormField(
controller: _emailController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Email",
errorText: _errorMessage,
),
validator: (value) {
if (value == null || value.isEmpty) {
return "Please Enter Your Email";
}
return null;
},
onTap: () {
setState(() {
_showSuccessMessage = false;
});
},
onChanged: (value) {
setState(() {
_email = value;
_errorMessage = null;
});
},
),
SizedBox(height: 20),
TextFormField(
controller: _passController,
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Password",
),
validator: (value) {
if (value == null || value.isEmpty) {
return "Please Enter Your Password";
}
final hasUppercase = RegExp(r'[A-Z]').hasMatch(value);
final hasLowercase = RegExp(r'[a-z]').hasMatch(value);
final hasDigits = RegExp(r'[0-9]').hasMatch(value);
final hasSpecialCharacters = RegExp(r'[!@#$%^&*(),.?":{}|<>]').hasMatch(value);
if (!hasUppercase) {
return "Password must contain at least one uppercase letter.";
}
if (!hasLowercase) {
return "Password must contain at least one lowercase letter.";
}
if (!hasDigits) {
return "Password must contain at least one digit.";
}
if (!hasSpecialCharacters) {
return "Password must contain at least one special character.";
}
return null;
},
onTap: () {
setState(() {
_showSuccessMessage = false;
});
},
onChanged: (value) {
setState(() {
_password = value;
_showSuccessMessage = false;
});
},
),
Column(
children: [
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_handleSignUp();
}
},
child: Text("Sign Up"),
),
SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Do you have an account?"),
TextButton(
onPressed: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => LoginScreen()),
);
},
child: Text("Login"),
),
],
),
],
),
],
),
),
),
),
);
}
}
Happy coding!