Email Authentication Using Firebase In Flutter
Firebase is one of the recommended Back-End for Flutter applications since it gives many accessible functionalities and extraordinary integration with Flutter. One of the highlights offered by Firebase is Authentication. This way we can integrate Email, Phone, Google, Apple, and a lot more authentications in our applications!
In this article, we will use the firebase_auth package for Firebase Authentication.
If you’re looking for the best Flutter app development company for your mobile application then feel free to contact us at — support@flutterdevs.com.
Table Of Contents::
Introduction:
The demo video below shows how to implement Email Authentication using Firebase in Flutter, and also how we can sign-up or login using email, we have made a demo app similar to the famous social media app Instagram, this provides users the option to both sign-up and log-in using email and password, and this can be achieved all because of Firebase.
The user can also interact with the posts on the home page but more on that later, let’s start with the integration of Email Authentication using Firebase.
Demo Modules::
Implementation:
Step 1: Enabling Email/Password Authentication from Firebase Console
Once you have added your project and app to Firebase Console, the first step is to enable Authentication and enable Email/Password from it.
When you click on Authentication, you will get a welcome screen from where you can click on Get Started.
When you click on the button, you will be redirected to the Sign In Method list. From there you can enable Email/Password.
Now that the first step is done, let’s dive deep into the coding part.
Step 2: Adding the dependencies
Add dependencies to pubspec — yaml file.
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.0
firebase_core: ^1.Conclusion:0.0
cloud_firestore: ^1.0.0
firebase_auth: ^1.0.0
firebase_storage: ^8.0.0
provider: ^5.0.0
Step 3: Run flutter packages get in the root directory of your app.
How to implement code in dart file :
We will create sign-up and log-in screens, You need to implement them in your code respectively:
Create a new dart file called signup_screen.dart
inside the lib
folder.
We will create a sign-up form page which will be a stateful widget, which will be responsible for signing up users.
import 'package:flutter/material.dart';
import '../services/auth_methods.dart';
import '../utils/utils.dart';
class SignupScreen extends StatefulWidget {
static final String id = 'signup_screen';
@override
_SignupScreenState createState() => _SignupScreenState();
}
class _SignupScreenState extends State<SignupScreen> {
final _formKey = GlobalKey<FormState>();
String? _name;
String? _email;
String? _password;
String? _userName;
bool _isLoading = false;
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'Instagram',
style: TextStyle(
fontFamily: 'Billabong',
fontSize: 50.0,
),
),
Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(
horizontal: 30.0,
vertical: 10.0,
),
child: TextFormField(
decoration: InputDecoration(labelText: 'Name'),
validator: (input) => input!.trim().isEmpty
? 'Please enter a valid name'
: null,
onSaved: (input) => _name = input!,
),
),Padding(
padding: EdgeInsets.symmetric(
horizontal: 30.0,
vertical: 10.0,
),
child: TextFormField(
decoration: InputDecoration(labelText: 'Username'),
validator: (input) => input!.trim().isEmpty
? 'Please enter a valid username'
: null,
onSaved: (input) => _userName = input!,
),
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: 30.0,
vertical: 10.0,
),
child: TextFormField(
decoration: InputDecoration(labelText: 'Email'),
validator: (input) => !input!.contains('@')
? 'Please enter a valid email'
: null,
onSaved: (input) => _email = input!,
),
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: 30.0,
vertical: 10.0,
),
child: TextFormField(
decoration: InputDecoration(labelText: 'Password'),
validator: (input) => input!.length < 6
? 'Must be at least 6 characters'
: null,
onSaved: (input) => _password = input!,
obscureText: true,
),
),
SizedBox(height: 20.0),
Padding(
padding: EdgeInsets.only(
left: 40,
right: 40,
),
child: Container(
width: double.infinity,
color: Colors.blue,
child: _isLoading
? Center(
child: CircularProgressIndicator(
color: Colors.white,
),
)
: TextButton(
onPressed: () => _signUp(),
child: Text(
'Sign Up',
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
),
),
),
),
),
SizedBox(height: 20.0),
Container(
color: Colors.blue,
padding: EdgeInsets.symmetric(horizontal: 50),
child: TextButton(
onPressed: () => Navigator.pop(context),
child: Text(
'Back to Login',
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
),
),
),
),
],
),
),
],
),
),
),
);
}
}
When we run the application, we ought to get the screen’s output like the underneath screen capture.
Create a new dart file called login_screen.dart
inside the lib
folder.
We will create a login page where users that signed up using email and password can directly log in.
import 'package:demo_email_authentication/screens/signup_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:io';
import '../services/auth_methods.dart';
import '../utils/utils.dart';
class LoginScreen extends StatefulWidget {
static final String id = 'login_screen';
@override
_LoginScreenState createState() => new _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final TextEditingController _emailIdController = new TextEditingController();
final TextEditingController _passwordController = new TextEditingController();
bool _isLoading = false;
var _textStyleBlack = new TextStyle(fontSize: 12.0, color: Colors.black);
var _textStyleGrey = new TextStyle(fontSize: 12.0, color: Colors.grey);
var _textStyleBlueGrey =
new TextStyle(fontSize: 12.0, color: Colors.blueGrey);
@override
void dispose() {
super.dispose();
_emailIdController.dispose();
_passwordController.dispose();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
bottomNavigationBar: _bottomBar(),
body: _body(),
);
}
Widget _userIDEditContainer() {
return new Container(
child: new TextField(
controller: _emailIdController,
decoration: new InputDecoration(
hintText: 'Phone number, email or username',
border: new OutlineInputBorder(
borderSide: new BorderSide(color: Colors.black),
),
isDense: true),
style: _textStyleBlack,
),
);
}
Widget _passwordEditContainer() {
return Container(
padding: EdgeInsets.only(top: 5.0),
child: TextField(
controller: _passwordController,
obscureText: true,
decoration: InputDecoration(
hintText: 'Password',
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
isDense: true),
style: _textStyleBlack,
),
);
}
Widget _loginContainer() {
return GestureDetector(
onTap: _logInUser,
child: Container(
alignment: Alignment.center,
margin: EdgeInsets.only(top: 10.0),
width: 500.0,
height: 40.0,
child: _isLoading
? Center(
child: CircularProgressIndicator(
color: Colors.white,
),
)
: Text(
"Log In",
style: TextStyle(color: Colors.white),
),
color: Colors.blue,
),
);
}
Widget _facebookContainer() {
return Container(
alignment: Alignment.center,
margin: EdgeInsets.only(top: 10.0),
width: 500.0,
height: 40.0,
color: Colors.blue,
child: GestureDetector(
onTap: null,
child: Text(
"Log in with facebook",
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
),
);
}
Widget _bottomBar() {
return Container(
alignment: Alignment.center,
height: 49.5,
child: Column(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
height: 1.0,
color: Colors.grey.withOpacity(0.7),
),
Padding(
padding: EdgeInsets.only(bottom: 0.5),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Don\'t have an account?', style: _textStyleGrey),
Container(
child: TextButton(
onPressed: () =>
Navigator.pushNamed(context, SignupScreen.id),
child: Text('Sign Up.', style: _textStyleGrey),
),
),
],
)),
],
),
],
),
);
}
Widget _body() {
return Container(
alignment: Alignment.center,
padding: EdgeInsets.all(25.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 25.0, bottom: 15.0),
child: Text(
'Instagram',
style: TextStyle(fontFamily: 'Billabong', fontSize: 50.0),
),
),
_userIDEditContainer(),
_passwordEditContainer(),
_loginContainer(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Forgot your login details?',
style: _textStyleGrey,
),
TextButton(
onPressed: () {},
child: Text(
'Get help logging in.',
style: _textStyleBlueGrey,
),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
height: 1.0,
width: MediaQuery.of(context).size.width / 2.7,
color: Colors.grey,
child: ListTile(),
),
Text(
' OR ',
style: TextStyle(color: Colors.blueGrey),
),
Container(
height: 1.0,
width: MediaQuery.of(context).size.width / 2.7,
color: Colors.grey,
),
],
),
_facebookContainer()
],
),
);
}
_showEmptyDialog(String title) {
if (Platform.isAndroid) {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) => AlertDialog(
content: Text("$title can't be empty"),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text("OK"))
],
),
);
} else if (Platform.isIOS) {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) => CupertinoAlertDialog(
content: Text("$title can't be empty"),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text("OK"))
],
),
);
}
}
}
When we run the application, we ought to get the screen’s output like the underneath screen capture.
Now let’s initialize firebase in our app, inmain.dart
inside thelib
folder.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
The WidgetsFlutterBinding.ensureInitialized();
ensures that the UI is not rendered until our initialization is not done.
Next, we will create a new dart file calledauth_methods.dart
This will contain the two most required functions for email authentication using firebase, i.e. sign-up and log-in.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import '../models/user_model.dart';
class AuthMethods {
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<String> signUpUser({
required String? name,
required String? email,
required String? password,
required String? username,
}) async {
String result = 'Some error occurred';
try {
if (email!.isNotEmpty || name!.isNotEmpty || password!.isNotEmpty) {
UserCredential user = await _auth.createUserWithEmailAndPassword(
email: email, password: password!);
print(user.user!.uid);
UserModel userModel = UserModel(
email: email,
name: name!,
uid: user.user!.uid,
username: username!,
followers: [],
following: [],
);
await _firestore.collection('users').doc(user.user!.uid).set(
userModel.toJson(),
);
result = 'success';
}
} catch (err) {
result = err.toString();
}
return result;
}
Future<String> logInUser({
required String email,
required String password,
}) async {
String result = 'Some error occurred';
try {
if (email.isNotEmpty || password.isNotEmpty) {
await _auth.signInWithEmailAndPassword(
email: email, password: password);
result = 'success';
}
} catch (err) {
result = err.toString();
}
return result;
}
}
Along these lines, as we are involving Firebase for Authentication, we have pre-constructed methods for log-in and sign-up. For sign-up, we can implement createUserWithEmailAndPassword which takes 2 parameters i.e. email and password, and some parameters like name and email for our app. Likewise, we can utilize signInWithEmailAndPassword which similarly takes 2 parameters i.e. email and password. Here, we made two user-defined methods to deal with our Firebase calls. These methods accept email and password as parameters and pass them to the Firebase functions.
Here, if you notice, we are using UserModel
. We have just created a simple model class that looks like this:
import 'package:cloud_firestore/cloud_firestore.dart';
class UserModel{
final String email;
final String name;
final String uid;
final String username;
final List followers;
final List following;
UserModel(
{required this.email,
required this.name,
required this.username,
required this.uid,
required this.followers,
required this.following});
Map<String, dynamic> toJson() => {
"email": email,
"uid": uid,
"name": name,
"username": username,
"followers": followers,
"following": following,
};
static UserModel? fromSnap (DocumentSnapshot snap) {
var snapshot = snap.data() as Map<String, dynamic>;
return UserModel(
username: snapshot['username'],
uid: snapshot['uid'],
name: snapshot['name'],
following: snapshot['following'],
followers: snapshot['followers'],
email: snapshot['email'],
);
}
}
Finally we create a new dart file called home_screen.dart
inside the lib
folder.
This screen will reflect if the user successfully signs up or logs in using Email Authentication. When we run the application, we ought to get the screen’s output like the underneath screen capture.
Now that all the methods are ready in our auth_methods.dart file,
Let’s implement these methods in our UI,
void _signUp() async {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
setState(() {
_isLoading = true;
});
// Logging in the user w/ Firebase
String result = await AuthMethods()
.signUpUser(name: _name, email: _email, password: _password, username: _userName);
if (result != 'success') {
showSnackBar(result, context);
} else {
Navigator.pop(context);
}
setState(() {
_isLoading = false;
});
}
}
We can call the above function in the onPressed method of the sign-up button.
You can check out the sign-up method demo in the demo modules above.
Let’s do the same for the log-in button,
void _logInUser() async {
if (_emailIdController.text.isEmpty) {
_showEmptyDialog("Type something");
} else if (_passwordController.text.isEmpty) {
_showEmptyDialog("Type something");
}
setState(() {
_isLoading = true;
});
String result = await AuthMethods().logInUser(
email: _emailIdController.text,
password: _passwordController.text,
);
if (result == 'successs') {
} else {
showSnackBar(result, context);
}
setState(() {
_isLoading = false;
});
}
You can check out the log-in method demo in the demo modules above.
Conclusion:
In the article, I have shed some light on the fundamental construction of Email Authentication using Firebase in a flutter program, you can modify this code as per your need. This was a little prologue to Email Authentication using Firebase from my side, and its functioning using Flutter.
I trust this blog will give you adequate data on trying up Email Authentication using Firebase in your flutter projects. We showed you what Email Authentication using Firebase is. its implementations, and how to utilize Email Authentication using Firebase. Made a demo app to work in your flutter applications. So if it’s not too much trouble, try it.
❤ ❤ Thanks for reading this article ❤❤
If I got something wrong? Let me know in the comments. I would love to improve.
Clap 👏 If this article helps you.
GitHub Link:
find the source code of the Flutter Email Authentication using Firebase Demo:
GitHub – flutter-devs/email_authentication_using_firebase
A new Flutter project. This project is a starting point for a Flutter application. A few resources to get you started…github.com
Feel free to connect with us:
And read more articles from FlutterDevs.com.
FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire a flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter-related queries.
We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences.