Firebase Authentication provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users to your app. It supports authentication using passwords, phone numbers, popular federated identity providers like Google, Facebook, and Twitter, and more. Integrating Firebase Authentication in a Flutter app can be streamlined with the FlutterFire plugins, providing a seamless way to manage user authentication. This comprehensive guide will walk you through integrating Firebase Authentication into your Flutter app.
What is Firebase Authentication?
Firebase Authentication is a service that provides backend services to authenticate users. It is a secure and easy-to-use platform that simplifies user authentication in your app. It manages the complexity of setting up an authentication backend, reducing the time and effort required to get user authentication up and running.
Why Use Firebase Authentication?
- Ease of Use: Simple SDKs to handle user authentication without managing backend complexities.
- Multiple Authentication Methods: Supports email/password, phone number, Google, Facebook, and other providers.
- Security: Secure handling of authentication credentials.
- Scalability: Reliably handles a large number of users with Google’s infrastructure.
- Integration: Seamless integration with other Firebase services.
Prerequisites
Before integrating Firebase Authentication, make sure you have:
- Flutter SDK installed.
- Firebase project created.
- FlutterFire CLI installed (for Firebase setup).
Step-by-Step Integration
Step 1: Create a New Flutter Project
If you don’t already have one, create a new Flutter project:
flutter create firebase_auth_example
Step 2: Set Up Firebase Project
First, initialize FlutterFire in your Flutter project. Run the following command in the project directory:
flutterfire configure
Select the Firebase project you want to use and follow the prompts. This step automatically configures your Flutter app for Firebase, generating necessary configuration files like firebase_options.dart.
Step 3: Install Required Dependencies
Add the necessary Firebase Authentication dependencies to your pubspec.yaml file:
dependencies:
firebase_core: ^2.15.0
firebase_auth: ^4.6.3
Then, run flutter pub get to install the packages.
Step 4: Initialize Firebase in Flutter
In your main.dart file, initialize Firebase:
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Firebase Auth Example',
home: AuthenticationWrapper(),
);
}
}
Step 5: Create an Authentication Wrapper
Create a widget that checks the authentication state and navigates the user to the appropriate screen. Here’s an example of an AuthenticationWrapper widget:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'home_screen.dart';
import 'login_screen.dart';
class AuthenticationWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return HomeScreen();
}
return LoginScreen();
},
);
}
}
Step 6: Implement Login Screen
Create a LoginScreen widget that handles user login.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class LoginScreen extends StatefulWidget {
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
Future<void> _signInWithEmailAndPassword() async {
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
} on FirebaseAuthException catch (e) {
print("Failed with error code: ${e.code}");
print(e.message);
// Handle errors (e.g., show error message to user)
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Login')),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
),
TextField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _signInWithEmailAndPassword,
child: Text('Login'),
),
TextButton(
child: Text('Don't have an account? Sign Up'),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => SignupScreen()),
);
},
),
],
),
),
);
}
@override
void dispose() {
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
}
Step 7: Implement Sign-Up Screen
Create a SignupScreen to handle new user registrations:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class SignupScreen extends StatefulWidget {
@override
_SignupScreenState createState() => _SignupScreenState();
}
class _SignupScreenState extends State<SignupScreen> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
Future<void> _createUserWithEmailAndPassword() async {
try {
await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
} on FirebaseAuthException catch (e) {
print("Failed with error code: ${e.code}");
print(e.message);
// Handle errors (e.g., show error message to user)
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Sign Up')),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
),
TextField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _createUserWithEmailAndPassword,
child: Text('Sign Up'),
),
],
),
),
);
}
@override
void dispose() {
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
}
Step 8: Implement Home Screen
Create a simple HomeScreen widget where authenticated users are redirected:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
actions: [
IconButton(
icon: Icon(Icons.exit_to_app),
onPressed: () async {
await FirebaseAuth.instance.signOut();
},
),
],
),
body: Center(
child: Text('Logged in Successfully!'),
),
);
}
}
Handling User Authentication States
Using the authStateChanges() stream from FirebaseAuth.instance is crucial for understanding the user’s current authentication state. The AuthenticationWrapper component utilizes this stream to navigate users appropriately, either to the LoginScreen if unauthenticated or to the HomeScreen if authenticated.
StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.hasData) {
// User is signed in
return HomeScreen();
} else {
// No user is signed in
return LoginScreen();
}
},
);
Sign Out
The signOut() method is invoked from the HomeScreen via a button, enabling users to sign out of the application:
IconButton(
icon: Icon(Icons.exit_to_app),
onPressed: () async {
await FirebaseAuth.instance.signOut();
},
),
Conclusion
Integrating Firebase Authentication in Flutter using FlutterFire offers a straightforward solution for managing user authentication. By following the steps outlined above, you can quickly add authentication features to your Flutter apps. Remember to handle exceptions and provide feedback to users for a better experience. Leverage other Firebase services alongside authentication for even more powerful app capabilities.