image

02 Mar 2026

9K

35K

Flutter & Firebase Auth: Implementing Multi-Provider Login

Modern applications frequently require users to sign in using various methods, enhancing user convenience and accessibility. Implementing multi-provider login can be a complex task, but with Flutter and Firebase Authentication, it becomes significantly more manageable. This article will guide you through building a multi-provider login system in Flutter, leveraging Firebase Auth and the provider package for robust state management.

Why Multi-Provider Login?

Offering multiple login options (e.g., email/password, Google, Facebook) provides several benefits:

  • Improved User Experience: Users can choose their preferred login method, often one they already use and trust.
  • Wider Reach: Accommodates users who might not want to create a new password or remember another set of credentials.
  • Reduced Friction: Social logins often allow for a quicker sign-up and login process.

Prerequisites

  • A basic understanding of Flutter development.
  • A Firebase project set up with Flutter integration.
  • Familiarity with the provider package is beneficial.

Step 1: Flutter Project and Firebase Setup

1.1 Flutter Project Creation

If you don't have a Flutter project, create one:


flutter create flutter_multi_auth
cd flutter_multi_auth

1.2 Add Dependencies

Add the necessary dependencies to your pubspec.yaml file:


dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^2.24.2 # Or the latest version
  firebase_auth: ^4.15.2 # Or the latest version
  provider: ^6.0.5 # Or the latest version
  google_sign_in: ^6.1.6 # Or the latest version for Google Sign-In
  flutter_facebook_auth: ^6.1.0 # Or the latest version for Facebook Sign-In

Run flutter pub get to fetch the packages.

1.3 Firebase Project Configuration

Ensure your Firebase project is correctly configured for your Flutter app (Android, iOS, Web). Then, enable the desired sign-in methods in the Firebase console (Authentication > Sign-in method):

  1. Email/Password: Enable this method.
  2. Google: Enable this method. Follow the instructions to configure your SHA-1 key for Android and GoogleService-Info.plist for iOS.
  3. Facebook: Enable this method. You'll need an app created in the Facebook Developer Console. Provide the App ID and App Secret to Firebase. For Android and iOS, also configure your AndroidManifest.xml and Info.plist respectively as per flutter_facebook_auth package documentation for URL schemes and meta-data.

Step 2: Defining the Authentication Service

We'll create a dedicated service to encapsulate all Firebase Authentication logic. This promotes clean architecture and testability.

2.1 User Model

A simple model to represent our authenticated user:


// lib/models/app_user.dart
import 'package:firebase_auth/firebase_auth.dart';

class AppUser {
  final String? uid;
  final String? email;
  final String? displayName;
  final String? photoURL;

  AppUser({this.uid, this.email, this.displayName, this.photoURL});

  factory AppUser.fromFirebaseUser(User? user) {
    return AppUser(
      uid: user?.uid,
      email: user?.email,
      displayName: user?.displayName,
      photoURL: user?.photoURL,
    );
  }
}

2.2 FirebaseAuthService

This service will handle all interactions with firebase_auth.


// lib/services/auth_service.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import '../models/app_user.dart';

class AuthService {
  final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
  final GoogleSignIn _googleSignIn = GoogleSignIn();
  final FacebookAuth _facebookAuth = FacebookAuth.instance;

  // Stream to observe user authentication state
  Stream<AppUser?> get user {
    return _firebaseAuth.authStateChanges().map(AppUser.fromFirebaseUser);
  }

  // Sign in with Email and Password
  Future<AppUser?> signInWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _firebaseAuth.signInWithEmailAndPassword(
        email: email,
        password: password,
      );
      return AppUser.fromFirebaseUser(result.user);
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  // Register with Email and Password
  Future<AppUser?> registerWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _firebaseAuth.createUserWithEmailAndPassword(
        email: email,
        password: password,
      );
      return AppUser.fromFirebaseUser(result.user);
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  // Sign in with Google
  Future<AppUser?> signInWithGoogle() async {
    try {
      final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
      if (googleUser == null) return null; // User cancelled the sign-in

      final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
      final AuthCredential credential = GoogleAuthProvider.credential(
        accessToken: googleAuth.accessToken,
        idToken: googleAuth.idToken,
      );

      UserCredential result = await _firebaseAuth.signInWithCredential(credential);
      return AppUser.fromFirebaseUser(result.user);
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  // Sign in with Facebook
  Future<AppUser?> signInWithFacebook() async {
    try {
      final LoginResult result = await _facebookAuth.login();

      if (result.status == LoginStatus.success) {
        final accessToken = result.accessToken;
        if (accessToken == null) return null;

        final AuthCredential credential = FacebookAuthProvider.credential(accessToken.token);
        UserCredential userCredential = await _firebaseAuth.signInWithCredential(credential);
        return AppUser.fromFirebaseUser(userCredential.user);
      } else if (result.status == LoginStatus.cancelled) {
        print('Facebook login cancelled.');
        return null;
      } else {
        print('Facebook login failed: ${result.message}');
        return null;
      }
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  // Sign out
  Future<void> signOut() async {
    try {
      await _googleSignIn.signOut();
      await _facebookAuth.logOut();
      await _firebaseAuth.signOut();
    } catch (e) {
      print(e.toString());
    }
  }
}

Step 3: Integrating with Provider for State Management

We'll use the provider package to make our AuthService available throughout the widget tree and to reactively update the UI based on the user's authentication state.

3.1 main.dart

Initialize Firebase and provide the AuthService.


// lib/main.dart
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:provider/provider.dart';
import 'firebase_options.dart'; // Generated by FlutterFire CLI

import 'services/auth_service.dart';
import 'models/app_user.dart';
import 'screens/login_screen.dart';
import 'screens/home_screen.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        Provider<AuthService>(
          create: (_) => AuthService(),
        ),
        StreamProvider<AppUser?>(
          create: (context) => context.read<AuthService>().user,
          initialData: null,
        ),
      ],
      child: MaterialApp(
        title: 'Flutter Multi Auth',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: const AuthWrapper(),
      ),
    );
  }
}

// Widget to handle navigation based on auth state
class AuthWrapper extends StatelessWidget {
  const AuthWrapper({super.key});

  @override
  Widget build(BuildContext context) {
    final AppUser? user = Provider.of<AppUser?>(context);

    if (user == null) {
      return const LoginScreen();
    } else {
      return const HomeScreen();
    }
  }
}

Step 4: Building the User Interface

4.1 Login Screen

This screen will provide input fields for email/password and buttons for social logins.


// lib/screens/login_screen.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../services/auth_service.dart';

class LoginScreen extends StatefulWidget {
  const LoginScreen({super.key});

  @override
  State<LoginScreen> createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  final TextEditingController _emailController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();

  @override
  void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final authService = Provider.of<AuthService>(context);

    return Scaffold(
      appBar: AppBar(title: const Text('Login')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextField(
              controller: _emailController,
              decoration: const InputDecoration(labelText: 'Email'),
            ),
            TextField(
              controller: _passwordController,
              decoration: const InputDecoration(labelText: 'Password'),
              obscureText: true,
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                final user = await authService.signInWithEmailAndPassword(
                  _emailController.text,
                  _passwordController.text,
                );
                if (user == null) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Failed to sign in with email/password.')),
                  );
                }
              },
              child: const Text('Sign In with Email'),
            ),
            TextButton(
              onPressed: () async {
                final user = await authService.registerWithEmailAndPassword(
                  _emailController.text,
                  _passwordController.text,
                );
                if (user == null) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Failed to register with email/password.')),
                  );
                } else {
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Registration successful!')),
                  );
                }
              },
              child: const Text('Register with Email'),
            ),
            const SizedBox(height: 20),
            ElevatedButton.icon(
              icon: Image.asset('assets/google_logo.png', height: 24), // Add a Google logo asset
              label: const Text('Sign In with Google'),
              onPressed: () async {
                final user = await authService.signInWithGoogle();
                if (user == null) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Failed to sign in with Google.')),
                  );
                }
              },
            ),
            const SizedBox(height: 10),
            ElevatedButton.icon(
              icon: Image.asset('assets/facebook_logo.png', height: 24), // Add a Facebook logo asset
              label: const Text('Sign In with Facebook'),
              onPressed: () async {
                final user = await authService.signInWithFacebook();
                if (user == null) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Failed to sign in with Facebook.')),
                  );
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

Note: You'll need to add google_logo.png and facebook_logo.png to your assets/ folder and declare the folder in pubspec.yaml.

4.2 Home Screen

A simple screen displayed after successful login, showing user info and a logout button.


// lib/screens/home_screen.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../services/auth_service.dart';
import '../models/app_user.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final authService = Provider.of<AuthService>(context);
    final AppUser? user = Provider.of<AppUser?>(context);

    return Scaffold(
      appBar: AppBar(
        title: const Text('Home'),
        actions: <Widget>[
          IconButton(
            icon: const Icon(Icons.logout),
            onPressed: () async {
              await authService.signOut();
            },
          ),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Welcome, ${user?.displayName ?? user?.email ?? 'User'}!'),
            if (user?.photoURL != null)
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: CircleAvatar(
                  radius: 50,
                  backgroundImage: NetworkImage(user!.photoURL!),
                ),
              ),
            const Text('You are successfully logged in.'),
          ],
        ),
      ),
    );
  }
}

Conclusion

Implementing a multi-provider login system in Flutter with Firebase Authentication and the provider package significantly streamlines the development process. By abstracting authentication logic into a dedicated service and managing state reactively, you can create a robust, scalable, and user-friendly authentication flow. This setup not only offers flexibility to your users but also maintains a clean and maintainable codebase.

Related Articles

May 14, 2026

Building a Multi-Event Countdown Timer Widget with Reminders, Notifications, Repeat, and Custom Labels in Flutter

Building a Multi-Event Countdown Timer Widget with Reminders, Notifications, Repeat, and Custom Labels in Flutter Countdown timers are essential in many applic

May 11, 2026

Unleashing Dynamic UIs: Flutter's Animation Prowess

Unleashing Dynamic UIs: Flutter's Animation Prowess for Slide & Scale Effects Flutter's declarative UI framework, combined with its powerful animation capabilit

May 11, 2026

Building a Product Detail Page Widget in Flutter with Related Items, Review Carousel, Promo Badges, and Quick Buy

Building a Product Detail Page Widget in Flutter with Related Items, Review Carousel, Promo Badges, and Quick Buy A well-designed Product Detail Page (PDP) is