A production-oriented Flutter authentication project built with Firebase Authentication, Cloud Firestore, and Riverpod.
The project supports email/password authentication, Google Sign-In, email verification, password reset, password creation for Google accounts, profile management, and account deletion.
- Email/password registration
- Email/password sign in
- Google Sign-In
- Email verification
- Forgot password / password reset
- Password creation for Google-only accounts
- Change existing password
- Sign out
- Re-authentication for sensitive operations
- Account deletion with confirmation
- Support for accounts using:
- Google authentication
- Email/password authentication
- Both Google and email/password authentication
- Firestore user profiles
- Display name
- Email address
- Profile completion status
- Edit profile
- Real-time profile updates
- Profile state management with Riverpod
- Shows a sign-in button when the user is logged out
- Shows the user's display name when logged in
- Provides access to the profile page
- Automatically updates authentication state
- Automatically reflects profile changes
Register
↓
Create Firebase Authentication user
↓
Create Firestore user document
↓
Send verification email
↓
Verify email
The Firestore user document is stored using the Firebase Authentication UID:
users/{uid}
Example:
{
"email": "user@example.com",
"displayName": "John",
"profileCompleted": false,
"createdAt": "server timestamp"
}Google users can initially create an account using Google authentication.
Google Sign-In
↓
Firebase Authentication
↓
Create Firestore profile
↓
Complete profile
A Google-only account can later create a password.
Google-only account
The user sees:
- Create password
- New password
- Confirm password
No current password is required because the account does not have a password credential yet.
After creating the password, the account has both:
google.compassword
The same Firebase UID is retained.
Account with password already linked
After a password has been created, the Change Password screen becomes:
- Current password
- New password
- Confirm password
The current password is required before changing the password.
The application distinguishes between two password operations.
-
Create Password
Used when a Google account does not have a password provider.Google account ↓ Create password ↓ linkPasswordCredential() -
Change Password
Used when the account already has an email/password provider.Current password ↓ Re-authenticate ↓ New password ↓ Update passwordThis prevents a user from changing a password without proving knowledge of the existing password.
Users can request a Firebase password-reset email.
Forgot password
↓
Enter email
↓
Firebase sends reset email
↓
Firebase reset link
↓
New password
Firebase generates the password reset code and handles its validity and expiration.
The reset code is not a permanent user identifier.
New email/password users receive an email verification message.
The application can refresh the Firebase user and check emailVerified.
The verification flow is separate from password reset.
Account deletion requires confirmation to prevent accidental deletion.
For password accounts:
Current password
↓
Re-authentication
↓
Confirmation dialog
↓
Delete Firebase account
For Google accounts, Google authentication is used for re-authentication.
After deletion, the application returns to the Home screen and clears the authenticated user state.
User profiles are stored under:
users/{uid}
The application uses the Firebase Authentication UID as the Firestore document ID.
class AppUser {
final String uid;
final String email;
final String? displayName;
final bool profileCompleted;
final DateTime createdAt;
}emaildisplayNameprofileCompletedcreatedAt
Example:
{
"email": "user@example.com",
"displayName": "John Doe",
"profileCompleted": true,
"createdAt": "server timestamp"
}The project uses Riverpod for application state management.
Important providers include:
authStateProvidercurrentUserProviderauthControllerProviderappUserProvideruserFirestoreServiceProviderfirebaseAuthServiceProvider
The application uses Firebase userChanges() rather than only authStateChanges().
This is important because Firebase user information can change while the user remains authenticated.
For example, linking a password to a Google account changes providerData without necessarily changing the authentication state.
Using userChanges() allows the application to immediately detect changes such as:
- Provider linking
- Display name changes
- Email changes
- Other Firebase user updates
- Sign in
- Sign out
lib/
│
├── core/
│ └── firebase/
│ └── firebase_options.dart
│
├── features/
│ ├── auth/
│ │ ├── data/
│ │ │ └── firebase_auth_service.dart
│ │ │
│ │ └── providers/
│ │ ├── auth_controller.dart
│ │ └── auth_provider.dart
│ │
│ └── user/
│ ├── data/
│ │ └── user_firestore_service.dart
│ │
│ ├── models/
│ │ └── app_user.dart
│ │
│ └── providers/
│ └── user_provider.dart
│
├── screens/
│ ├── auth_and_profile/
│ │ ├── login_screen.dart
│ │ ├── register_screen.dart
│ │ ├── verify_email_screen.dart
│ │ ├── forgot_password_screen.dart
│ │ ├── change_password_screen.dart
│ │ ├── profile_screen.dart
│ │ ├── edit_profile_screen.dart
│ │ ├── delete_account_screen.dart
│ │ └── complete_google_signup_screen.dart
│ │
│ └── home_screen.dart
│
├── utils/
│ └── form_validations.dart
│
├── widgets/
│ └── home_content.dart
│
└── main.dart
- Flutter
- Dart
- Firebase Authentication
- Cloud Firestore
- Firebase Google Sign-In
- Riverpod
The main packages used by the project include:
dependencies:
flutter:
sdk: flutter
firebase_core:
firebase_auth:
cloud_firestore:
flutter_riverpod:
google_sign_in:Use the versions defined in pubspec.yaml for the exact project configuration.
Before running the application, configure Firebase for your Flutter project.
Create a project in the Firebase Console.
Register your Android application using the correct package name.
Generate the Firebase configuration using FlutterFire CLI:
flutterfire configureThis generates the Firebase configuration used by:
lib/core/firebase/firebase_options.dart
In Firebase Authentication, enable:
- Email/Password
Create a Cloud Firestore database for the Firebase project.
The application expects the default Firestore database: (default)
For Android Google Sign-In, add the appropriate SHA-1 fingerprint to the Firebase Android application configuration.
You can obtain the debug signing report with:
cd android
./gradlew signingReport(On Windows: cd android, then .\gradlew.bat signingReport)
Add the required SHA-1 fingerprint in:
- Firebase Console
- Project Settings
- Your apps
- Android app
Then download/update the Firebase Android configuration if required.
- The Android package name must match the package registered in Firebase.
- Make sure Firebase configuration is correctly generated for the Android application.
- For Google Sign-In, the SHA-1 fingerprint is particularly important. Without the correct SHA-1 configuration, Google Sign-In can fail with errors such as
GoogleSignInException code.canceled.
The application uses the authenticated Firebase UID as the Firestore user document ID.
A basic security model is:
users/{uid}
Users should only be allowed to read and modify their own profile.
Example concept:
request.auth.uid == uidDo not deploy permissive Firestore rules such as allowing unrestricted reads and writes in a production application.
Clone the repository:
git clone https://github.com/elamany/complete_flutter_firebase_auth.gitEnter the project directory:
cd flutter-firebase-authInstall dependencies:
flutter pub getConfigure Firebase:
flutterfire configureRun the application:
flutter runFirebase configuration files contain project-specific configuration.
Do not accidentally commit sensitive or environment-specific configuration files if your project setup requires them to remain private.
- FlutterFire generated configuration:
lib/core/firebase/firebase_options.dart - Android Firebase configuration:
android/app/google-services.json
Make sure your repository strategy is appropriate for your Firebase project and deployment environment.
The application separates responsibilities into services, providers, controllers, models, screens, and reusable widgets.
- Authentication service (
FirebaseAuthService): Responsible for Firebase Authentication operations (Create account, Sign in, Google Sign-In, Sign out, Send verification email, Password reset, Update password, Link password credential, Re-authentication, Delete account, Update display name). - Authentication controller (
AuthController): Responsible for coordinating UI actions with the authentication service, exposed throughauthControllerProvider. - User Firestore service (
UserFirestoreService): Responsible for Firestore profile operations (Create user profile, Read user profile, Watch user profile, Update profile). - User provider (
appUserProvider): Provides the Firestore profile reactively by watching the Firebase authentication user and then watchingusers/{uid}.
Firebase Authentication and Firestore have separate responsibilities.
- Firebase Authentication: Stores authentication-related information (UID, Email, Authentication providers, Password credential, Email verification status).
- Firestore: Stores application-specific profile information (Display name, Profile completion, Created timestamp, Other application profile fields).
The Firebase UID connects the two systems:
Firebase Auth UID ───> users/{uid}
- The project uses Firebase Authentication for identity management instead of storing passwords in Firestore.
- Passwords should never be stored manually in Firestore.
- Sensitive operations such as changing a password or deleting an account should require recent authentication when Firebase requires it.
- Password reset is handled through Firebase's password-reset mechanism rather than storing reset credentials in the application database.
- Firestore access should be protected with security rules so users cannot access another user's profile.
User can:
- Sign in with email/password
- Change password
- Reset password
- Delete account
User can:
- Sign in with Google
- Create a password
- Delete account
User can:
- Sign in with Google
- Sign in with email/password
- Change password
- Reset password
- Delete account
New email user
Create account ➔ Verify email ➔ Home ➔ Profile ➔ Edit profile
New Google user
Google Sign-In ➔ Complete profile ➔ Create password (optional) ➔ Profile
Google user later creates password
Google Sign-In ➔ Profile ➔ Create password ➔ Password linked ➔ Email/password login available
Existing password user
Email/password sign in ➔ Profile ➔ Change password ➔ Current password ➔ New password & Confirm password
Authentication and core profile functionality are implemented, including:
- Email/password registration
- Email/password login
- Google Sign-In
- Email verification
- Forgot password
- Password reset
- Google account password creation
- Password change
- Profile display
- Profile editing
- Sign out
- Account deletion
- Firestore user profiles
- Riverpod authentication state
- Riverpod profile state
- Firebase user change synchronization
Possible future additions include:
- Profile photo upload
- Username uniqueness
- Phone authentication
- Two-factor authentication
- Account linking UI
- More advanced profile fields
- Better error localization
- Automated tests
- Widget tests
- Integration tests
- Production Firestore security rules
- App-wide authentication guards
- Loading/error state improvements