Build and publish a Flutter-based app for the App Store and Google Play — updated for 2026 with current FlutterFire packages, the latest Firebase Authentication APIs, and notes on what has changed since this series began.
Let's create an authenticated end user.
TL:DR – Authentication is built into Firebase. The heavy lifting is handled for you, so you can stay focused on what makes your app unique. Now, that story is even stronger thanks to the Identity Platform upgrade and a much-improved FlutterFire SDK.
Contents
- Authentication to Firebase and its Cloud Firestore database
- 2026 update: what has changed since this series began
- Add the dependencies to pubspec.yaml
- Initialise Firebase in main.dart
- Enable the Phone Sign-in provider in the Firebase console
- Build the sign-in flow
- Listening to authentication state
- Next steps
Authentication to Firebase and its Cloud Firestore database
We are going to get our app to authenticate its connection to Firebase Cloud Firestore. That requires the FlutterFire suite of plugins, which is now the single canonical home for all Firebase Flutter packages. The old split between FirebaseExtended/flutterfire and the Flutter plugins repo has been resolved — everything lives under the firebase/flutterfire repository and is actively maintained by the Firebase team.
Firebase Authentication supports a wide range of identity providers and sign-in methods out of the box:
- Apple
- Twitter / X
- GitHub
- Email and password
- Phone number (SMS)
- Anonymous users
- Custom auth systems via JWT tokens
- SAML and generic OpenID Connect providers (Identity Platform upgrade required)
Firebase Authentication is built on open standards — OAuth 2.0 and OpenID Connect — so the tokens it issues are interoperable with the broader ecosystem.
2026 update: what has changed since this series began
When the earlier parts of this series were written, FlutterFire packages were at early version numbers (firebase_auth: ^0.16, firebase_core: ^0.4) and the API surface was still settling. A lot has changed:
- Null-safe, fully migrated packages. All FlutterFire packages are now null-safe and have been for several years. Version numbers are in the single-digit majors (for example
firebase_auth: ^5.x,firebase_core: ^3.x). Always check pub.dev for the latest stable release before pinning a version. - Firebase CLI and FlutterFire CLI. The recommended way to wire up Firebase to a Flutter project is now the
flutterfire configurecommand from the FlutterFire CLI. It generates afirebase_options.dartfile automatically for every target platform, replacing the manualgoogle-services.jsonandGoogleService-Info.plistcopy-paste workflow. - Firebase Dynamic Links is retired. The
firebase_dynamic_linkspackage that appeared in the original dependencies is no longer available — Firebase Dynamic Links was shut down in 2025. If you need deep linking, migrate to a third-party solution such as uni_links or the App Links / Universal Links approach baked into the platform SDKs. - Identity Platform upgrade. Firebase now offers an upgrade path to Firebase Authentication with Identity Platform. This unlocks multi-factor authentication (MFA), blocking functions, user activity and audit logging, SAML providers, multi-tenancy, and enterprise-level support — all from the same Firebase console.
- FirebaseUI for Flutter. The Firebase team now describes FlutterFire UI as the recommended starting point for a complete sign-in flow. It provides pre-built, themeable sign-in and registration screens that handle the boilerplate so you can focus on customisation rather than plumbing.
FirebaseUI Auth is the recommended way to add a complete sign-in system to your app.
Add the dependencies to pubspec.yaml
The dependency list has changed meaningfully since the original article. firebase_dynamic_links is gone. The google_sign_in package is still needed for Google Sign-In on Android and iOS. We now initialise Firebase via firebase_options.dart (generated by the FlutterFire CLI) rather than through manual platform configuration files.
Run flutterfire configure first to generate firebase_options.dart, then add your dependencies. The version numbers below are illustrative — always pin to the latest stable release shown on pub.dev:
dependencies:
flutter:
sdk: flutter
# Firebase core — always required
firebase_core: ^3.0.0
# Authentication
firebase_auth: ^5.0.0
# Cloud Firestore
cloud_firestore: ^5.0.0
# Google Sign-In (required for Google auth on mobile)
google_sign_in: ^6.0.0
# Utility
uuid: ^4.0.0
Install dependencies from the command line with flutter pub get, or trigger it from the IDE when pubspec.yaml is open. Note that firebase_dynamic_links has been removed — if your project still references it, replace that functionality before upgrading.
Initialise Firebase in main.dart
With the FlutterFire CLI workflow, initialisation is straightforward and works consistently across all platforms. The generated firebase_options.dart contains the per-platform configuration, so there is no longer any need to manually edit AndroidManifest.xml or the Xcode project for basic setup:
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
Enable the Phone Sign-in provider in the Firebase console
Phone authentication still needs to be explicitly enabled in the Firebase console. Navigate to Authentication → Sign-in method, select the Phone provider and enable it. Add at least one test phone number so you can verify the flow during development without consuming real SMS quota. Save your changes.

If you have upgraded to Identity Platform, you will also see options here for SAML providers, OpenID Connect providers, and multi-factor authentication settings.
Build the sign-in flow
Rather than copying raw example code from GitHub as the original article described, the current recommended approach is to use FlutterFire UI. It provides ready-made SignInScreen and RegisterScreen widgets that handle the full authentication flow — including error states and loading indicators — and are easy to theme to match your app.
If you prefer full control and want to wire up authentication manually, the official example code now lives at firebase/flutterfire — firebase_auth example. The structure is similar to what was described in the original article, but the API calls reflect the current null-safe SDK.
We are still using routes to manage screen transitions, so adding the new pages remains straightforward:
routes: {
'/': (context) => FirstPage(),
'/Establishments': (context) => MyHomePage(),
'/SignInPage': (context) => SignInPage(),
'/RegisterPage': (context) => RegisterPage(),
},
Add two IconButton actions to the AppBar to surface the new routes during development:
IconButton(
icon: const Icon(
Icons.person_add,
semanticLabel: 'Test Registration',
),
onPressed: () {
Navigator.pushNamed(context, '/RegisterPage');
},
),
IconButton(
icon: const Icon(
Icons.person_outline,
semanticLabel: 'Test SignIn/SignOut',
),
onPressed: () {
Navigator.pushNamed(context, '/SignInPage');
},
),

Test the components before styling them. Tap Sign in anonymously and the anonymous user should appear almost immediately in the Firebase console under Authentication → Users. Getting an authenticated user connected really is that straightforward.

Listening to authentication state
One thing worth highlighting that the original article glossed over: in the current SDK, the right way to react to sign-in and sign-out events throughout your app is to listen to the authStateChanges() stream. This replaces any manual state management you might have wired up previously:
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user == null) {
print('User is signed out.');
} else {
print('User is signed in: ${user.uid}');
}
});
Wrapping your top-level widget tree in a StreamBuilder keyed to authStateChanges() is a clean pattern for gating content behind authentication without scattering sign-in checks across individual screens.
Next steps
The app can now create an authenticated user — anonymously, via Google, or through email and password. The next step is to put that identity to work: letting a signed-in user create, read, update, and delete data in Cloud Firestore, with security rules that enforce ownership at the database level.