How to Use Firebase to Sign In and Register your Flutter App
In native app development, whether working on a simple application or building your dream app, one thing is for sure — authentication makes it super easy to personalize the experience! How? Thanks to user-specific information, of course. It’s also a crucial component of privacy and security. Nowadays, to make it easier Firebase becomes a handy tool to do that as we don’t need to maintain any backend infrastructure for the authentication process and also Firebase supports integration with popular identity providers such as Google, Facebook, and GitHub.
In this blog, we will show you Flutter login and registration using Firebase. In other words. We will show you how to use Firebase Authentication in your Flutter App, so that the user can sign-up and after that log in to use your app easily.
But first, let’s get to know what is Flutter and Firebase.
What is Flutter?
Flutter is an open-source UI software development kit created by Google. It is used to develop cross-platform applications for Android, iOS, Linux, macOS, Windows, Google Fuchsia, and the web from a single codebase.
What is Firebase?
Firebase is a Google-backed application development software that enables developers to develop iOS, Android, and Web apps. It is a pre-configured backend service that makes it easy to integrate with a mobile app using an SDK.
Now, let’s move to setting things into motion!
Head to Android studio: Go to the Android Studio and create a new project. Follow the pattern of the project name and package name from the below image and remember the package name because we will need it later.
After creating a new project, you will get main.dart under the lib folder which is the default starting file of this project. You can rename this file anytime you want.
Now, create 2 subfolders under the lib folder and named them screens and helper. After that, create 3 dart files under the screens folder named login_screen, signup_screen, and home_screen. Now, create another 2 dart files under the helper folder named firebase_auth and validator.
Now, to authenticate our app with firebase authentication, we need to go to our google firebase console and start a new project. Follow this link to go to your firebase console https://console.firebase.google.com/
After opening your firebase console click on add/start a new project. You can give any name you wish and press continue.
Enable google analytics for this project and press continue.
Select Default Account for Firebase and Create Project.
It might take 10–15 seconds and then you will be all set to use Firebase for authentication of your flutter app and carry out login authentication in Flutter.
Now, we will learn how to set up our firebase project for android. Click on the android button below on this screen of your firebase project and you will be redirected to a page to set up your android application.
It’s crucial to give an android package name to our android app. Now remember that I had told you earlier to keep the package name in mind? But wait, if you can’t remember this, we have a way to find this.
Go to the app-level build.gradle file. You need to head over there and locate the applicationId tag in your build.gradle file. That will be the name you need to put in your Android Package name.
After completing this step, you need to click on Register App. Then you need to download the google-services.json file. Now after downloading this file make sure you drag or place this file in the android/app folder of your Flutter project.
Now there are a few other things we need to do before we are done with the settings of our android app. Open up your project-level build.gradle, file and add then copy the dependencies to your build.gradle file.
Then we need to open our app-level build.gradle file and copy and add the dependencies to our app-level build.gradle file. Now, you are all set up to use firebase authentication in your project.
We will need two modules to use Firebase in your Flutter project for authentication.
- firebase_core- A Flutter plugin to use the Firebase Core API, which enables connecting to multiple Firebase apps. Visit this link to know more about the firebase_core
- firebase_auth- A Flutter plugin to use the Firebase Authentication API. Visit this link to know more about the firebase_auth
Next, we will need to update our pubspec.yaml file and update the dependencies to use these modules. This is how your dependencies should look in your pubspec.yaml file. After updating the dependencies make sure you click on Pub Get.
And another thing! You need to change the minimum sdk version to 19 so that the latest version of dependencies will work. To do that, go to the app level build.gradle file and replace the minimum sdk version with 19 in the nextline of the applicationId.
Before going to coding, we need to deal with Flutter Firebase auth email password! For this, we need to enable the email-password authentication feature from Firebase. Click on Authentication as you see in the below image.
After clicking on it, you are redirected to the next page. Now click on Get Started.
You can see we have lots of options to enable authentication in our app. We have Facebook, Apple, Google, Github, etc. and we can use all of these.
As of now, we will use the simple email-password feature to understand how it works. Click on the Email/Password and click the enable button and save it.
So, the setup part is finished now. Let’s move on to the code now. I will suggest you not to copy this code. Try to write it.
firebase_auth.dart
import 'package:firebase_auth/firebase_auth.dart';
class FirebaseAuthHelper {
static Future<User?> registerUsingEmailPassword({
required String name,
required String email,
required String password,
}) async {
FirebaseAuth auth = FirebaseAuth.instance;
User? user;
try {
UserCredential userCredential = await auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
user = userCredential.user;
await user!.updateProfile(displayName: name);
await user.reload();
user = auth.currentUser;
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
return user;
}
static Future<User?> signInUsingEmailPassword({
required String email,
required String password,
}) async {
FirebaseAuth auth = FirebaseAuth.instance;
User? user;
try {
UserCredential userCredential = await auth.signInWithEmailAndPassword(
email: email,
password: password,
);
user = userCredential.user;
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided.');
}
}
return user;
}
}
validator.dart
class Validator {
static String? validateName({required String? name}) {
if (name == null) {
return null;
}
if (name.isEmpty) {
return 'Name can\'t be empty';
}
return null;
}
static String? validateEmail({required String? email}) {
if (email == null) {
return null;
}
RegExp emailRegExp = RegExp(
r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$");
if (email.isEmpty) {
return 'Email can\'t be empty';
} else if (!emailRegExp.hasMatch(email)) {
return 'Enter a correct email';
}
return null;
}
static String? validatePassword({required String? password}) {
if (password == null) {
return null;
}
if (password.isEmpty) {
return 'Password can\'t be empty';
} else if (password.length < 6) {
return 'Enter a password with length at least 6';
}
return null;
}
}
main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'screens/login_screen.dart';
void 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(
title: 'SJI Info',
debugShowCheckedModeBanner: false,
theme: ThemeData(
brightness: Brightness.light,
primarySwatch: Colors.blue,
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
textStyle: const TextStyle(
fontSize: 24.0,
),
padding: const EdgeInsets.fromLTRB(16.0, 8.0, 16.0, 8.0),
),
),
textTheme: TextTheme(
headline1: TextStyle(
fontSize: 46.0,
color: Colors.blue.shade700,
fontWeight: FontWeight.w500,
),
bodyText1: const TextStyle(fontSize: 18.0),
),
),
home: LoginScreen(),
);
}
}
login_screen.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:sji_info/screens/home_screen.dart';
import 'package:sji_info/screens/signup_screen.dart';
import '../helper/firebase_auth.dart';
import '../helper/validator.dart';
class LoginScreen extends StatefulWidget {
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _formKey = GlobalKey<FormState>();
final _emailTextController = TextEditingController();
final _passwordTextController = TextEditingController();
final _focusEmail = FocusNode();
final _focusPassword = FocusNode();
bool _isProcessing = false;
Future<FirebaseApp> _initializeFirebase() async {
FirebaseApp firebaseApp = await Firebase.initializeApp();
User? user = FirebaseAuth.instance.currentUser;
if (user != null) {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => HomeScreen(
user: user,
),
),
);
}
return firebaseApp;
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
_focusEmail.unfocus();
_focusPassword.unfocus();
},
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepOrangeAccent,
title: Text('SJI Info'),
centerTitle: true,
),
body: FutureBuilder(
future: _initializeFirebase(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Padding(
padding: const EdgeInsets.only(left: 24.0, right: 24.0,top: 48),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
height: 150,
width: 150,
child: Image.asset("sji_logo.png"),
),
const Padding(
padding: EdgeInsets.only(bottom: 30.0,top: 12),
child: Text(
'Welcome to SJI',
style: TextStyle(
color: Colors.black,
fontSize: 40
)
),
),
Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: _emailTextController,
focusNode: _focusEmail,
validator: (value) => Validator.validateEmail(
email: value,
),
decoration: InputDecoration(
hintText: "Email",
errorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(6.0),
borderSide: BorderSide(
color: Colors.red,
),
),
),
),
SizedBox(height: 8.0),
TextFormField(
controller: _passwordTextController,
focusNode: _focusPassword,
obscureText: true,
validator: (value) => Validator.validatePassword(
password: value,
),
decoration: InputDecoration(
hintText: "Password",
errorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(6.0),
borderSide: BorderSide(
color: Colors.red,
),
),
),
),
SizedBox(height: 24.0),
_isProcessing
? CircularProgressIndicator()
: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: ElevatedButton(
onPressed: () async {
_focusEmail.unfocus();
_focusPassword.unfocus();
if (_formKey.currentState!
.validate()) {
setState(() {
_isProcessing = true;
});
User? user = await FirebaseAuthHelper
.signInUsingEmailPassword(
email: _emailTextController.text,
password:
_passwordTextController.text,
);
setState(() {
_isProcessing = false;
});
if (user != null) {
Navigator.of(context)
.pushReplacement(
MaterialPageRoute(
builder: (context) =>
HomeScreen(user: user),
),
);
}
}
},
child: Text(
'Sign In',
style: TextStyle(color: Colors.white),
),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.deepOrangeAccent),
),
),
),
SizedBox(width: 24.0),
Expanded(
child: ElevatedButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
SignUpScreen(),
),
);
},
child: Text(
'SignUp',
style: TextStyle(color: Colors.white),
),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.deepOrangeAccent),
),
),
),
],
)
],
),
)
],
),
);
}
return const Center(
child: CircularProgressIndicator(),
);
},
),
),
);
}
}
signup_screen.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:sji_info/screens/home_screen.dart';
import 'package:sji_info/helper/firebase_auth.dart';
import 'package:sji_info/helper/validator.dart';
class SignUpScreen extends StatefulWidget {
@override
_SignUpScreenState createState() => _SignUpScreenState();
}
class _SignUpScreenState extends State<SignUpScreen> {
final _registerFormKey = GlobalKey<FormState>();
final _nameTextController = TextEditingController();
final _emailTextController = TextEditingController();
final _passwordTextController = TextEditingController();
final _focusName = FocusNode();
final _focusEmail = FocusNode();
final _focusPassword = FocusNode();
bool _isProcessing = false;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
_focusName.unfocus();
_focusEmail.unfocus();
_focusPassword.unfocus();
},
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepOrangeAccent,
title: Text('Create Account'),
centerTitle: true,
),
body: Padding(
padding: const EdgeInsets.all(24.0),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Form(
key: _registerFormKey,
child: Column(
children: <Widget>[
TextFormField(
controller: _nameTextController,
focusNode: _focusName,
validator: (value) => Validator.validateName(
name: value,
),
decoration: InputDecoration(
hintText: "Name",
errorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(6.0),
borderSide: BorderSide(
color: Colors.red,
),
),
),
),
SizedBox(height: 12.0),
TextFormField(
controller: _emailTextController,
focusNode: _focusEmail,
validator: (value) => Validator.validateEmail(
email: value,
),
decoration: InputDecoration(
hintText: "Email",
errorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(6.0),
borderSide: BorderSide(
color: Colors.red,
),
),
),
),
SizedBox(height: 12.0),
TextFormField(
controller: _passwordTextController,
focusNode: _focusPassword,
obscureText: true,
validator: (value) => Validator.validatePassword(
password: value,
),
decoration: InputDecoration(
hintText: "Password",
errorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(6.0),
borderSide: BorderSide(
color: Colors.red,
),
),
),
),
SizedBox(height: 32.0),
_isProcessing
? CircularProgressIndicator()
: Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: () async {
setState(() {
_isProcessing = true;
});
if (_registerFormKey.currentState!
.validate()) {
User? user = await FirebaseAuthHelper
.registerUsingEmailPassword(
name: _nameTextController.text,
email: _emailTextController.text,
password:
_passwordTextController.text,
);
setState(() {
_isProcessing = false;
});
if (user != null) {
Navigator.of(context)
.pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) =>
HomeScreen(user: user),
),
ModalRoute.withName('/'),
);
}
}else{
setState(() {
_isProcessing = false;
});
}
},
child: Text(
'Sign up',
style: TextStyle(color: Colors.white),
),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.deepOrangeAccent),
),
),
),
],
)
],
),
)
],
),
),
),
),
);
}
}
home_screen.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:sji_info/screens/login_screen.dart';
import 'package:sji_info/helper/firebase_auth.dart';
class HomeScreen extends StatefulWidget {
final User user;
HomeScreen({required this.user});
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late User _currentUser;
@override
void initState() {
_currentUser = widget.user;
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepOrangeAccent,
title: Text('HomeScreen'),
centerTitle: true,
),
body: WillPopScope(
onWillPop: () async {
final logout = await showDialog<bool>(
context: context,
builder: (context) {
return AlertDialog(
title: new Text('Are you sure?'),
content: new Text('Do you want to logout from this App'),
actionsAlignment: MainAxisAlignment.spaceBetween,
actions: [
TextButton(
onPressed: () {
Logout();
},
child: const Text('Yes'),
),
TextButton(
onPressed: () {
Navigator.pop(context, false);
},
child: const Text('No'),
),
],
);
},
);
return logout!;
},
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'NAME: ${_currentUser.displayName}',
style: Theme.of(context).textTheme.bodyText1,
),
SizedBox(height: 16.0),
Text(
'EMAIL: ${_currentUser.email}',
style: Theme.of(context).textTheme.bodyText1,
),
SizedBox(height: 16.0),
ElevatedButton(
onPressed: () async {
await FirebaseAuth.instance.signOut();
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => LoginScreen(),
),
);
},
child: const Text('Sign out'),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.redAccent),
),
),
],
),
),
)
);
}
Future<dynamic> Logout() async {
await FirebaseAuth.instance.signOut();
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => LoginScreen(),
),
);
}
}
After writing this code just run this.
BOOM!!! You’ve successfully added Firebase Authentication in your Flutter app.
If you want to explore this Flutter login and registration using Firebase, you will find this code on my GitHub repository.
If you have any suggestions or questions about this login authentication in Flutter, feel free to get in touch with our native app development experts or hire a mobile app developer or connect with me on LinkedIn or Facebook.
Create your next mobile app with our expert team! Learn how to implement Firebase for login and registration in Flutter in our blog. Click here to read now and discover our mobile app development services.