Skip to main content
RapidDev - Software Development Agency
firebase-tutorial

How to Use Firebase Auth with Flutter

To use Firebase Auth with Flutter, add the FlutterFire packages (firebase_core and firebase_auth) to your project and run the FlutterFire CLI to auto-generate platform configuration. Use StreamBuilder with FirebaseAuth.instance.authStateChanges() to reactively rebuild the UI when the user signs in or out. Firebase Auth in Flutter supports email/password, Google Sign-In, Apple Sign-In, phone authentication, and anonymous auth out of the box.

What you'll learn

  • How to configure FlutterFire using the CLI for automatic platform setup
  • How to implement email/password sign-up, sign-in, and sign-out flows
  • How to listen to auth state changes with StreamBuilder for reactive UI
  • How to add Google Sign-In with the google_sign_in package
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate8 min read20-25 minFlutter 3.x+, firebase_core 3.x+, firebase_auth 5.x+, all Firebase plansMarch 2026RapidDev Engineering Team
TL;DR

To use Firebase Auth with Flutter, add the FlutterFire packages (firebase_core and firebase_auth) to your project and run the FlutterFire CLI to auto-generate platform configuration. Use StreamBuilder with FirebaseAuth.instance.authStateChanges() to reactively rebuild the UI when the user signs in or out. Firebase Auth in Flutter supports email/password, Google Sign-In, Apple Sign-In, phone authentication, and anonymous auth out of the box.

Implementing Firebase Authentication in Flutter

FlutterFire provides official Firebase plugins for Flutter that work across iOS, Android, web, and desktop. This tutorial walks through configuring Firebase in a Flutter project using the FlutterFire CLI, implementing email/password authentication with sign-up and login screens, reacting to auth state changes with StreamBuilder, and adding Google Sign-In as an OAuth provider. You will build a complete auth flow that persists user sessions and handles errors gracefully.

Prerequisites

  • Flutter SDK 3.x+ installed with a working development environment
  • A Firebase project created in the Firebase Console
  • FlutterFire CLI installed (dart pub global activate flutterfire_cli)
  • Email/Password sign-in enabled in Firebase Console > Authentication > Sign-in method

Step-by-step guide

1

Configure Firebase with the FlutterFire CLI

The FlutterFire CLI auto-generates platform-specific configuration files so you do not need to manually add google-services.json or GoogleService-Info.plist. Run flutterfire configure in your project root, select your Firebase project, and choose the platforms you want to configure. The CLI creates a firebase_options.dart file with your Firebase config.

typescript
1# Install FlutterFire CLI
2dart pub global activate flutterfire_cli
3
4# Run configuration (select your Firebase project)
5flutterfire configure
6
7# Add Firebase packages to pubspec.yaml
8flutter pub add firebase_core firebase_auth

Expected result: A lib/firebase_options.dart file is generated with platform-specific configuration for your Firebase project.

2

Initialize Firebase in your app

Call Firebase.initializeApp() in your main() function before running the app. Pass the DefaultFirebaseOptions from the generated firebase_options.dart file. This must complete before any Firebase service is used.

typescript
1import 'package:firebase_core/firebase_core.dart';
2import 'package:flutter/material.dart';
3import 'firebase_options.dart';
4
5void main() async {
6 WidgetsFlutterBinding.ensureInitialized();
7 await Firebase.initializeApp(
8 options: DefaultFirebaseOptions.currentPlatform,
9 );
10 runApp(const MyApp());
11}

Expected result: Firebase is initialized and all Firebase services (Auth, Firestore, etc.) are available throughout the app.

3

Implement email/password sign-up and sign-in

Use FirebaseAuth.instance to access auth methods. createUserWithEmailAndPassword() registers new users, and signInWithEmailAndPassword() logs in existing users. Both return a UserCredential containing the User object. Wrap calls in try-catch to handle errors like weak-password, email-already-in-use, and wrong-password.

typescript
1import 'package:firebase_auth/firebase_auth.dart';
2
3class AuthService {
4 final FirebaseAuth _auth = FirebaseAuth.instance;
5
6 Future<String?> signUp(String email, String password) async {
7 try {
8 await _auth.createUserWithEmailAndPassword(
9 email: email,
10 password: password,
11 );
12 return null; // success
13 } on FirebaseAuthException catch (e) {
14 return e.message; // return error message
15 }
16 }
17
18 Future<String?> signIn(String email, String password) async {
19 try {
20 await _auth.signInWithEmailAndPassword(
21 email: email,
22 password: password,
23 );
24 return null;
25 } on FirebaseAuthException catch (e) {
26 return e.message;
27 }
28 }
29
30 Future<void> signOut() async {
31 await _auth.signOut();
32 }
33
34 User? get currentUser => _auth.currentUser;
35}

Expected result: Users can create accounts and sign in with email and password, with errors returned as human-readable messages.

4

React to auth state changes with StreamBuilder

FirebaseAuth.instance.authStateChanges() returns a Stream that emits the current User whenever the auth state changes (sign in, sign out, token refresh). Use StreamBuilder at the top of your widget tree to switch between authentication screens and the main app based on the current user.

typescript
1import 'package:firebase_auth/firebase_auth.dart';
2import 'package:flutter/material.dart';
3
4class AuthGate extends StatelessWidget {
5 const AuthGate({super.key});
6
7 @override
8 Widget build(BuildContext context) {
9 return StreamBuilder<User?>(
10 stream: FirebaseAuth.instance.authStateChanges(),
11 builder: (context, snapshot) {
12 // Show loading indicator while checking auth state
13 if (snapshot.connectionState == ConnectionState.waiting) {
14 return const Scaffold(
15 body: Center(child: CircularProgressIndicator()),
16 );
17 }
18
19 // User is signed in
20 if (snapshot.hasData) {
21 return const HomeScreen();
22 }
23
24 // User is not signed in
25 return const LoginScreen();
26 },
27 );
28 }
29}

Expected result: The app automatically navigates between login and home screens when the user signs in or out.

5

Add Google Sign-In

Google Sign-In requires the google_sign_in package for the native flow and GoogleAuthProvider from firebase_auth. The user signs in with Google first (which shows the native account picker), then the Google credential is used to authenticate with Firebase. Enable Google as a sign-in provider in the Firebase Console.

typescript
1import 'package:google_sign_in/google_sign_in.dart';
2import 'package:firebase_auth/firebase_auth.dart';
3
4Future<String?> signInWithGoogle() async {
5 try {
6 // Trigger the Google Sign-In flow
7 final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
8 if (googleUser == null) return 'Sign-in cancelled';
9
10 // Get auth details from the Google account
11 final GoogleSignInAuthentication googleAuth =
12 await googleUser.authentication;
13
14 // Create a Firebase credential
15 final credential = GoogleAuthProvider.credential(
16 accessToken: googleAuth.accessToken,
17 idToken: googleAuth.idToken,
18 );
19
20 // Sign in to Firebase with the Google credential
21 await FirebaseAuth.instance.signInWithCredential(credential);
22 return null; // success
23 } catch (e) {
24 return e.toString();
25 }
26}
27
28// Add to pubspec.yaml: google_sign_in: ^6.0.0

Expected result: Users can sign in with their Google account using the native account picker, and the session is managed by Firebase Auth.

6

Protect routes and display user info

Once authenticated, access the current user's information through FirebaseAuth.instance.currentUser. Use this to display the user's email, name, or photo, and to protect screens that require authentication. The User object provides uid, email, displayName, photoURL, and emailVerified properties.

typescript
1import 'package:firebase_auth/firebase_auth.dart';
2import 'package:flutter/material.dart';
3
4class HomeScreen extends StatelessWidget {
5 const HomeScreen({super.key});
6
7 @override
8 Widget build(BuildContext context) {
9 final user = FirebaseAuth.instance.currentUser!;
10
11 return Scaffold(
12 appBar: AppBar(
13 title: const Text('Home'),
14 actions: [
15 IconButton(
16 icon: const Icon(Icons.logout),
17 onPressed: () => FirebaseAuth.instance.signOut(),
18 ),
19 ],
20 ),
21 body: Center(
22 child: Column(
23 mainAxisAlignment: MainAxisAlignment.center,
24 children: [
25 if (user.photoURL != null)
26 CircleAvatar(
27 backgroundImage: NetworkImage(user.photoURL!),
28 radius: 40,
29 ),
30 const SizedBox(height: 16),
31 Text('Welcome, ${user.displayName ?? user.email}'),
32 Text('UID: ${user.uid}'),
33 ],
34 ),
35 ),
36 );
37 }
38}

Expected result: The home screen displays the authenticated user's name, photo, and UID with a sign-out button.

Complete working example

auth_service.dart
1import 'package:firebase_auth/firebase_auth.dart';
2import 'package:google_sign_in/google_sign_in.dart';
3
4class AuthService {
5 final FirebaseAuth _auth = FirebaseAuth.instance;
6
7 // Auth state stream for StreamBuilder
8 Stream<User?> get authStateChanges => _auth.authStateChanges();
9
10 // Current user (may be null)
11 User? get currentUser => _auth.currentUser;
12
13 // Email/password sign-up
14 Future<String?> signUp(String email, String password) async {
15 try {
16 await _auth.createUserWithEmailAndPassword(
17 email: email,
18 password: password,
19 );
20 return null;
21 } on FirebaseAuthException catch (e) {
22 return _mapErrorCode(e.code);
23 }
24 }
25
26 // Email/password sign-in
27 Future<String?> signIn(String email, String password) async {
28 try {
29 await _auth.signInWithEmailAndPassword(
30 email: email,
31 password: password,
32 );
33 return null;
34 } on FirebaseAuthException catch (e) {
35 return _mapErrorCode(e.code);
36 }
37 }
38
39 // Google Sign-In
40 Future<String?> signInWithGoogle() async {
41 try {
42 final googleUser = await GoogleSignIn().signIn();
43 if (googleUser == null) return 'Sign-in cancelled.';
44
45 final googleAuth = await googleUser.authentication;
46 final credential = GoogleAuthProvider.credential(
47 accessToken: googleAuth.accessToken,
48 idToken: googleAuth.idToken,
49 );
50
51 await _auth.signInWithCredential(credential);
52 return null;
53 } catch (e) {
54 return e.toString();
55 }
56 }
57
58 // Sign out
59 Future<void> signOut() async {
60 await GoogleSignIn().signOut();
61 await _auth.signOut();
62 }
63
64 // Map error codes to user-friendly messages
65 String _mapErrorCode(String code) {
66 switch (code) {
67 case 'weak-password':
68 return 'Password must be at least 6 characters.';
69 case 'email-already-in-use':
70 return 'An account with this email already exists.';
71 case 'invalid-email':
72 return 'Please enter a valid email address.';
73 case 'user-not-found':
74 return 'No account found with this email.';
75 case 'wrong-password':
76 return 'Incorrect password. Please try again.';
77 default:
78 return 'An error occurred. Please try again.';
79 }
80 }
81}

Common mistakes when using Firebase Auth with Flutter

Why it's a problem: Forgetting to call WidgetsFlutterBinding.ensureInitialized() before Firebase.initializeApp() in main()

How to avoid: Add WidgetsFlutterBinding.ensureInitialized() as the first line in main() before any async operations.

Why it's a problem: Not running flutterfire configure after changing Firebase project settings or adding platforms

How to avoid: Run flutterfire configure again whenever your Firebase project settings change. This regenerates firebase_options.dart.

Why it's a problem: Using currentUser directly in the widget tree instead of authStateChanges() with StreamBuilder

How to avoid: currentUser can be null during initialization. Use StreamBuilder with authStateChanges() for reactive, reliable auth state handling.

Why it's a problem: Not adding SHA-1 fingerprint for Android Google Sign-In, causing authentication to fail silently

How to avoid: Generate your debug SHA-1 with 'keytool -list -v -keystore ~/.android/debug.keystore' and add it in Firebase Console > Project Settings > Your Apps > Android.

Best practices

  • Use the FlutterFire CLI (flutterfire configure) for automatic platform configuration instead of manual setup
  • Create an AuthService class to encapsulate all authentication logic and keep widgets clean
  • Use StreamBuilder with authStateChanges() at the top of the widget tree for reactive auth routing
  • Map FirebaseAuthException error codes to user-friendly messages instead of showing raw error strings
  • Sign out of both Google and Firebase when implementing Google Sign-In sign-out
  • Enable only the sign-in providers you actually use in the Firebase Console to reduce attack surface
  • Test on both iOS and Android since platform-specific configuration differs (SHA-1, URL schemes)

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

Build Firebase Auth for a Flutter app. Show FlutterFire CLI setup, email/password sign-up and sign-in, authStateChanges with StreamBuilder, Google Sign-In with the google_sign_in package, error handling with user-friendly messages, and a sign-out flow.

Firebase Prompt

Create a Flutter AuthService class with Firebase Auth. Include email/password signup, signin, Google Sign-In, signOut, authStateChanges stream, and error code mapping. Use firebase_auth 5.x+ and google_sign_in. Also show the StreamBuilder auth gate widget.

Frequently asked questions

Do I need to manually add google-services.json and GoogleService-Info.plist?

No. The FlutterFire CLI (flutterfire configure) automatically generates and places these files. You only need to run the CLI and select your platforms.

Does Firebase Auth persist the login session in Flutter?

Yes. Firebase Auth automatically persists the session to secure storage on mobile devices. When the app restarts, the user remains signed in until they explicitly sign out.

How do I add Apple Sign-In to my Flutter app?

Add the sign_in_with_apple package, enable Apple as a sign-in provider in Firebase Console, configure your Apple Developer account with a Service ID, and use AppleAuthProvider with signInWithProvider().

What is the difference between authStateChanges and idTokenChanges?

authStateChanges emits when the user signs in or out. idTokenChanges also emits when the ID token is refreshed (e.g., after custom claims change). Use idTokenChanges if you need to react to token updates.

Can I use Firebase Auth without the FlutterFire CLI?

Yes, but it requires manual setup: downloading google-services.json, modifying build.gradle for Android, adding GoogleService-Info.plist to Xcode, and configuring each platform individually. The CLI automates all of this.

Can RapidDev help build a Flutter app with Firebase authentication?

Yes. RapidDev can implement complete authentication flows in Flutter including email/password, social login, phone auth, and role-based access control with Firestore custom claims.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.