image

10 May 2026

9K

35K

Flutter & Firebase Auth: Implementing SSO with Multiple OAuth2 Providers

In today's interconnected digital landscape, users often interact with applications using their existing accounts from popular identity providers like Google, Facebook, GitHub, or Apple. Implementing Single Sign-On (SSO) not only enhances user experience by eliminating the need to create new credentials but also improves security and simplifies user management. This article will guide you through building a Flutter application that leverages Firebase Authentication to enable SSO with multiple OAuth2 providers.

Why Single Sign-On (SSO)?

SSO offers significant advantages for both users and developers:

  • Enhanced User Experience: Users can log in with a single click using familiar accounts, reducing friction and improving onboarding.
  • Increased Security: Centralizing authentication reduces the surface area for credential attacks. Users are less likely to reuse weak passwords across different services.
  • Simplified Password Management: Users don't need to remember multiple passwords for your application.
  • Centralized User Management: Developers can manage user identities from various sources through a single platform.

Why Firebase Authentication?

Firebase Authentication is a powerful, fully-managed service that makes it easy to integrate secure authentication into your Flutter applications. Its key benefits include:

  • Ease of Integration: Provides SDKs for Flutter, Android, iOS, and Web, simplifying the setup process.
  • Support for Multiple Providers: Natively supports email/password, phone number, and popular OAuth2 providers like Google, Facebook, Twitter, GitHub, Apple, and more.
  • Security: Handles user data storage, hashing, and session management securely.
  • Scalability: Scales automatically with your user base without requiring infrastructure management.

1. Firebase Project Setup

Before diving into Flutter code, you need to configure your Firebase project:

1.1 Create a Firebase Project

Go to the Firebase Console, create a new project, and follow the on-screen instructions.

1.2 Enable Authentication Providers

Navigate to "Authentication" in your Firebase project, then go to the "Sign-in method" tab. Here, you'll enable the OAuth2 providers you wish to support. For each provider (e.g., Google, Facebook):

  1. Click "Enable".
  2. Follow the instructions to provide the necessary credentials (e.g., Google's Web client ID, Facebook's App ID and App Secret). You'll typically need to create an application for your project in the respective developer console (Google Cloud Console, Facebook for Developers).
  3. Firebase will provide a redirect URI (e.g., https://YOUR_PROJECT_ID.firebaseapp.com/__/auth/handler). You must add this URI to the authorized redirect URIs in your OAuth2 provider's developer console.

For mobile apps, specific setup is often required per platform (e.g., adding SHA-1 fingerprints for Android, Bundle IDs and App IDs for iOS).

2. Flutter Project Setup

Now, let's set up your Flutter application.

2.1 Create a New Flutter Project


flutter create flutter_sso_demo
cd flutter_sso_demo

2.2 Add Dependencies

Open your pubspec.yaml file and add the necessary Firebase and provider-specific packages:


dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^latest_version # e.g., ^2.24.2
  firebase_auth: ^latest_version # e.g., ^4.15.2
  google_sign_in: ^latest_version # e.g., ^6.2.1
  flutter_facebook_auth: ^latest_version # e.g., ^6.1.1
  # Add other providers like:
  # sign_in_with_apple: ^latest_version

Run flutter pub get to fetch the packages.

2.3 Configure Firebase for Flutter

Install the Firebase CLI and configure your Flutter project:


npm install -g firebase-tools # If not already installed
firebase login
flutterfire configure

This command will generate a firebase_options.dart file, which contains your platform-specific Firebase configuration.

2.4 Initialize Firebase in Your App

Update your main.dart to initialize Firebase:


import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart'; // Generated by flutterfire configure

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 MaterialApp(
      title: 'Flutter SSO Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const AuthScreen(),
    );
  }
}

3. Implementing Authentication Flow

Now, let's create a basic authentication screen and implement sign-in methods for Google and Facebook.

3.1 Google Sign-In

For Google Sign-In, we use the google_sign_in package to get the user's ID token and access token, then pass these to Firebase.


import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

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

  @override
  State createState() => _AuthScreenState();
}

class _AuthScreenState extends State {
  User? _currentUser;

  @override
  void initState() {
    super.initState();
    FirebaseAuth.instance.authStateChanges().listen((User? user) {
      setState(() {
        _currentUser = user;
      });
      if (user == null) {
        print('User is currently signed out!');
      } else {
        print('User is signed in! UID: ${user.uid}, Email: ${user.email}');
      }
    });
  }

  Future _signInWithGoogle() async {
    try {
      // Trigger the authentication flow
      final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();

      if (googleUser == null) {
        // The user canceled the sign-in
        return null;
      }

      // Obtain the auth details from the request
      final GoogleSignInAuthentication googleAuth = await googleUser.authentication;

      // Create a new credential
      final AuthCredential credential = GoogleAuthProvider.credential(
        accessToken: googleAuth.accessToken,
        idToken: googleAuth.idToken,
      );

      // Once signed in, return the UserCredential
      return await FirebaseAuth.instance.signInWithCredential(credential);
    } on FirebaseAuthException catch (e) {
      print("Firebase Auth Error for Google: ${e.message}");
      // Handle specific Firebase auth errors
    } catch (e) {
      print("Unknown Error for Google: $e");
    }
    return null;
  }

  // ... (Facebook sign-in and UI elements will go here)

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Firebase SSO Demo')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (_currentUser == null) ...[
              ElevatedButton.icon(
                onPressed: _signInWithGoogle,
                icon: Image.asset('assets/google_logo.png', height: 24), // Add a Google logo asset
                label: const Text('Sign in with Google'),
              ),
              const SizedBox(height: 16),
              // ... Facebook button
            ] else ...[
              Text('Welcome, ${_currentUser!.displayName ?? _currentUser!.email}!'),
              ElevatedButton(
                onPressed: _signOut,
                child: const Text('Sign Out'),
              ),
            ]
          ],
        ),
      ),
    );
  }

  Future _signOut() async {
    await FirebaseAuth.instance.signOut();
    await GoogleSignIn().signOut(); // Optional: clears Google session
    // await FlutterFacebookAuth.instance.logOut(); // Optional: clears Facebook session
  }
}

3.2 Facebook Sign-In

For Facebook Sign-In, you'll need the flutter_facebook_auth package. Make sure you've configured your Facebook App ID and client token in your android/app/src/main/AndroidManifest.xml and ios/Runner/Info.plist as per the package's documentation.


// ... inside _AuthScreenState class

  Future _signInWithFacebook() async {
    try {
      final LoginResult result = await FlutterFacebookAuth.instance.login(
        permissions: ['email', 'public_profile'],
      );

      if (result.status == LoginStatus.success) {
        final AccessToken accessToken = result.accessToken!;
        final AuthCredential credential = FacebookAuthProvider.credential(accessToken.token);
        return await FirebaseAuth.instance.signInWithCredential(credential);
      } else if (result.status == LoginStatus.cancelled) {
        print("Facebook login cancelled.");
        return null;
      } else {
        print("Facebook login failed: ${result.message}");
        return null;
      }
    } on FirebaseAuthException catch (e) {
      print("Firebase Auth Error for Facebook: ${e.message}");
    } catch (e) {
      print("Unknown Error for Facebook: $e");
    }
    return null;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Firebase SSO Demo')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (_currentUser == null) ...[
              ElevatedButton.icon(
                onPressed: _signInWithGoogle,
                icon: Image.asset('assets/google_logo.png', height: 24),
                label: const Text('Sign in with Google'),
              ),
              const SizedBox(height: 16),
              ElevatedButton.icon(
                onPressed: _signInWithFacebook,
                icon: Image.asset('assets/facebook_logo.png', height: 24), // Add a Facebook logo asset
                label: const Text('Sign in with Facebook'),
              ),
            ] else ...[
              Text('Welcome, ${_currentUser!.displayName ?? _currentUser!.email}!'),
              ElevatedButton(
                onPressed: _signOut,
                child: const Text('Sign Out'),
              ),
            ]
          ],
        ),
      ),
    );
  }

  Future _signOut() async {
    await FirebaseAuth.instance.signOut();
    await GoogleSignIn().signOut();
    await FlutterFacebookAuth.instance.logOut();
  }

3.3 Other Providers (GitHub, Apple, Twitter, etc.)

The pattern for other providers is similar:

  1. Use the respective Flutter package (e.g., sign_in_with_apple for Apple, or a custom web view solution for generic OAuth2).
  2. Obtain the necessary credentials (e.g., access token, ID token) from the provider.
  3. Create an AuthCredential using the specific provider's credential builder (e.g., GithubAuthProvider.credential(...), AppleAuthProvider.credential(...)).
  4. Call FirebaseAuth.instance.signInWithCredential(credential).

4. Linking Multiple Accounts (SSO for Existing Users)

Firebase Authentication allows you to link multiple identity providers to a single user account. This is crucial for SSO, as a user might initially sign up with Google, then later try to sign in with Facebook using the same email address. Firebase can automatically handle this if the emails match and are verified, merging the accounts. If the emails don't match, or if you want to explicitly allow linking, you can use linkWithCredential:


// Example: Linking a Google account to an already signed-in user
Future _linkGoogleAccount(User currentUser) async {
  try {
    final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
    if (googleUser == null) return null;

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

    return await currentUser.linkWithCredential(credential);
  } on FirebaseAuthException catch (e) {
    if (e.code == 'credential-already-in-use') {
      print('This Google account is already linked to another user.');
      // Handle this case, e.g., prompt user to sign in with that account
    } else {
      print("Error linking Google account: ${e.message}");
    }
    return null;
  } catch (e) {
    print("Unknown error linking Google account: $e");
    return null;
  }
}

You can then provide a UI option for signed-in users to link additional accounts.

5. Managing User State and Profile

The authStateChanges() stream is essential for reacting to authentication state changes throughout your app:


// Listen in initState or anywhere in your widget tree
FirebaseAuth.instance.authStateChanges().listen((User? user) {
  if (user == null) {
    print('User is currently signed out!');
  } else {
    print('User is signed in! UID: ${user.uid}');
    print('Display Name: ${user.displayName}');
    print('Email: ${user.email}');
    print('Photo URL: ${user.photoURL}');
    // Access provider-specific data
    for (final info in user.providerData) {
      print('Provider ID: ${info.providerId}, Email: ${info.email}');
    }
  }
});

The User object provides details like UID, email, display name, photo URL, and a list of linked providers.

6. Error Handling and Best Practices

  • Robust Error Handling: Always wrap your authentication calls in try-catch blocks to handle FirebaseAuthException and other potential errors (network issues, user cancellation).
  • UI/UX: Clearly label your sign-in buttons with provider logos. Provide clear feedback to users during the sign-in process.
  • Platform-Specific Configuration: Pay close attention to provider-specific setup instructions for Android and iOS (e.g., URL schemes, Info.plist entries, app IDs, package names, SHA-1 fingerprints).
  • Security Rules: Remember to configure Firebase Security Rules for your Firestore/Realtime Database to control data access based on authentication status.
  • Testing: Thoroughly test your authentication flow across all supported providers and platforms, including edge cases like network loss or user cancellation.

Conclusion

Implementing SSO with multiple OAuth2 providers in Flutter using Firebase Authentication is a streamlined and powerful approach. By following these steps, you can provide a seamless and secure login experience for your users, leveraging their existing identities and significantly reducing the complexity of managing authentication logic yourself. Firebase handles the heavy lifting, allowing you to focus on building great features for your application.

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