Flutter & Firebase Auth: Seamless Social Login with Google and Facebook
In today's mobile-first world, user authentication is a critical component of nearly every application. While traditional email and password methods are still prevalent, social logins offer a quicker, more convenient, and more secure way for users to access your services. This article explores how to integrate Google and Facebook social login into your Flutter application using Firebase Authentication, providing a robust and user-friendly authentication experience.
Why Social Login with Firebase Authentication?
Firebase Authentication provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users to your app. It supports authentication using passwords, phone numbers, and popular federated identity providers like Google, Facebook, Twitter, and GitHub. Combining Flutter's fast development cycle and beautiful UI capabilities with Firebase's powerful authentication backend offers several advantages:
- Enhanced User Experience: Users can sign in with existing social accounts, eliminating the need to create new credentials.
- Reduced Friction: One-tap sign-in leads to higher conversion rates and better user retention.
- Security: Firebase handles the complexities of secure authentication, protecting user data and credentials.
- Simplified Development: Firebase SDKs abstract away much of the boilerplate code, allowing developers to focus on core app features.
Prerequisites
Before diving into the implementation, ensure you have the following:
- Flutter SDK installed and configured.
- A Firebase project set up in the Firebase Console.
- Your Flutter app connected to your Firebase project (
google-services.jsonfor Android,GoogleService-Info.plistfor iOS).
Step 1: Firebase Project Configuration
First, you need to enable the authentication providers in your Firebase project.
1.1 Enable Google Sign-In
- Navigate to your Firebase project in the Firebase Console.
- In the left-hand menu, select Authentication > Sign-in method.
- Find Google in the list of sign-in providers and click the pencil icon to edit.
- Toggle the Enable switch to ON.
- Select a support email for your project and click Save.
- For Android, ensure you have added your SHA-1 fingerprint to your Firebase project settings under Project settings > General > Your apps > Android app > Add fingerprint. This is crucial for Google Sign-In to work.
1.2 Enable Facebook Sign-In
- You need a Facebook Developer account and an app created on the Facebook for Developers platform.
- From your Facebook Developer app dashboard, note down your App ID and App Secret.
- In the Firebase Console, navigate to Authentication > Sign-in method.
- Find Facebook and click the pencil icon.
- Toggle the Enable switch to ON.
- Enter your App ID and App Secret from your Facebook Developer app.
- Firebase will provide an OAuth redirect URI (e.g.,
https://YOUR_PROJECT_ID.firebaseapp.com/__/auth/handler). Copy this URI. - Go back to your Facebook Developer app dashboard. Under Products > Facebook Login > Settings, paste the Firebase OAuth redirect URI into the Valid OAuth Redirect URIs field.
- Also, ensure you have enabled "Web OAuth Login" in Facebook Login settings.
Step 2: Flutter Project Setup
Now, let's configure your Flutter project.
2.1 Add Dependencies
Open your pubspec.yaml file and add the following dependencies:
dependencies:
flutter:
sdk: flutter
firebase_core: ^2.24.2 # Or the latest version
firebase_auth: ^4.15.2 # Or the latest version
google_sign_in: ^6.1.0 # Or the latest version
flutter_facebook_auth: ^6.0.4 # Or the latest version (use the one compatible with Flutter 3+)
Run flutter pub get to fetch the packages.
2.2 Platform-Specific Configuration
Android Configuration
- Ensure
google-services.jsonis placed in yourandroid/appdirectory. - For Facebook Login, add the following to
android/app/src/main/AndroidManifest.xmlinside the<application>tag: - Create or modify
android/app/src/main/res/values/strings.xmland add your Facebook App ID, Client Token, and Protocol Scheme: - Make sure to replace
YOUR_FACEBOOK_APP_IDandYOUR_FACEBOOK_CLIENT_TOKEN. The client token can be found under "Settings > Advanced > Security" in your Facebook Developer Console.
<application ...>
<activity
android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
<meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token"/>
</application>
<resources>
<string name="app_name">your_app_name</string>
<string name="facebook_app_id">YOUR_FACEBOOK_APP_ID</string>
<string name="facebook_client_token">YOUR_FACEBOOK_CLIENT_TOKEN</string>
<string name="fb_login_protocol_scheme">fbYOUR_FACEBOOK_APP_ID</string>
</resources>
iOS Configuration
- Ensure
GoogleService-Info.plistis placed in yourios/Runnerdirectory and added to your Xcode project. - For Google Sign-In, you need to add a URL Scheme. In Xcode, open
ios/Runner.xcworkspace. Select your project in the Project Navigator, then go to Info > URL Types. Click the '+' button and add an entry with the URL Scheme from yourREVERSE_CLIENT_IDinGoogleService-Info.plist. - For Facebook Login, open
ios/Runner.xcworkspaceand add the following toios/Runner/Info.plist: - Also, open
ios/Runner/AppDelegate.swiftand add:
<key>CFBundleURLTypes</key>
<array>
<array>
<key>CFBundleURLSchemes</key>
<array>
<string>fbYOUR_FACEBOOK_APP_ID</string>
</array>
</array>
<array>
<key>CFBundleURLSchemes</key>
<array>
<string>YOUR_REVERSE_CLIENT_ID_FROM_GOOGLE_INFO_PLIST</string>
</array>
</array>
</array>
<key>FacebookAppID</key>
<string>YOUR_FACEBOOK_APP_ID</string>
<key>FacebookClientToken</key>
<string>YOUR_FACEBOOK_CLIENT_TOKEN</string>
<key>FacebookDisplayName</key>
<string>YOUR_APP_NAME</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>fbapi</string>
<string>fb-messenger-api</string>
<string>fbauth2</string>
<string>fbshareextension</string>
</array>
import UIKit
import Flutter
import Firebase
import flutter_facebook_auth // Add this import
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FirebaseApp.configure()
GeneratedPluginRegistrant.register(with: self)
// Add this for flutter_facebook_auth:
ApplicationDelegate.shared.application(
application,
didFinishLaunchingWithOptions: launchOptions
)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// Add this for flutter_facebook_auth:
override func application(
_ application: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey : Any] = [:]
) -> Bool {
ApplicationDelegate.shared.application(
application,
open: url,
options: options
)
}
}
Step 3: Initialize Firebase in Flutter
Ensure Firebase is initialized before using any Firebase services.
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Social Login Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AuthScreen(),
);
}
}
Step 4: Implement Google Sign-In
Create a dedicated screen or widget for authentication. Here's the core logic for Google Sign-In:
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 for Facebook later
import 'package:flutter/material.dart';
class AuthScreen extends StatefulWidget {
@override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State {
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
User? _user;
@override
void initState() {
super.initState();
_auth.authStateChanges().listen((user) {
setState(() {
_user = user;
});
});
}
Future<User?> _signInWithGoogle() async {
try {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser == null) {
// User cancelled the sign-in
return null;
}
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final UserCredential userCredential = await _auth.signInWithCredential(credential);
return userCredential.user;
} catch (e) {
print("Error signing in with Google: $e");
return null;
}
}
Future<void> _signOut() async {
await _auth.signOut();
await _googleSignIn.signOut();
await FlutterFacebookAuth.instance.logOut();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Firebase Social Login'),
),
body: Center(
child: _user == null
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton.icon(
onPressed: () async {
User? user = await _signInWithGoogle();
if (user != null) {
print("Google Sign-In successful: ${user.displayName}");
} else {
print("Google Sign-In failed or cancelled.");
}
},
icon: Image.asset(
'assets/google_logo.png', // Add a Google logo image to your assets
height: 24.0,
),
label: Text('Sign in with Google'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
foregroundColor: Colors.black,
minimumSize: Size(250, 50),
),
),
// Facebook button will go here
],
)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircleAvatar(
backgroundImage: NetworkImage(_user!.photoURL ?? ''),
radius: 50,
),
SizedBox(height: 20),
Text('Welcome, ${_user!.displayName ?? _user!.email}!'),
Text('UID: ${_user!.uid}'),
SizedBox(height: 20),
ElevatedButton(
onPressed: _signOut,
child: Text('Sign Out'),
),
],
),
),
);
}
}
Make sure to add a Google logo image to your assets folder and update pubspec.yaml to include the assets.
Step 5: Implement Facebook Sign-In
Now, let's add the Facebook Sign-In functionality to the same AuthScreen.
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 'package:flutter/material.dart';
class AuthScreen extends StatefulWidget {
@override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State {
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
final FlutterFacebookAuth _facebookAuth = FlutterFacebookAuth.instance;
User? _user;
@override
void initState() {
super.initState();
_auth.authStateChanges().listen((user) {
setState(() {
_user = user;
});
});
}
// ... (Google Sign-In and _signOut methods from above)
Future<User?> _signInWithFacebook() async {
try {
final LoginResult result = await _facebookAuth.login(
permissions: ['email', 'public_profile'],
);
if (result.status == LoginStatus.success) {
final AccessToken? accessToken = result.accessToken;
if (accessToken == null) {
print("Facebook access token is null.");
return null;
}
final AuthCredential credential = FacebookAuthProvider.credential(
accessToken.token,
);
final UserCredential userCredential = await _auth.signInWithCredential(credential);
return userCredential.user;
} else if (result.status == LoginStatus.cancelled) {
print("Facebook Sign-In cancelled.");
return null;
} else {
print("Facebook Sign-In failed: ${result.message}");
return null;
}
} catch (e) {
print("Error signing in with Facebook: $e");
return null;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Firebase Social Login'),
),
body: Center(
child: _user == null
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton.icon(
onPressed: () async {
User? user = await _signInWithGoogle();
if (user != null) {
print("Google Sign-In successful: ${user.displayName}");
} else {
print("Google Sign-In failed or cancelled.");
}
},
icon: Image.asset(
'assets/google_logo.png',
height: 24.0,
),
label: Text('Sign in with Google'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
foregroundColor: Colors.black,
minimumSize: Size(250, 50),
),
),
SizedBox(height: 20),
ElevatedButton.icon(
onPressed: () async {
User? user = await _signInWithFacebook();
if (user != null) {
print("Facebook Sign-In successful: ${user.displayName}");
} else {
print("Facebook Sign-In failed or cancelled.");
}
},
icon: Image.asset(
'assets/facebook_logo.png', // Add a Facebook logo image to your assets
height: 24.0,
),
label: Text('Sign in with Facebook'),
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF1877F2), // Facebook Blue
foregroundColor: Colors.white,
minimumSize: Size(250, 50),
),
),
],
)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircleAvatar(
backgroundImage: NetworkImage(_user!.photoURL ?? ''),
radius: 50,
),
SizedBox(height: 20),
Text('Welcome, ${_user!.displayName ?? _user!.email}!'),
Text('UID: ${_user!.uid}'),
SizedBox(height: 20),
ElevatedButton(
onPressed: _signOut,
child: Text('Sign Out'),
),
],
),
),
);
}
}
Remember to add a Facebook logo image to your assets folder and update pubspec.yaml.
Step 6: Handle Authentication State and Sign Out
The _auth.authStateChanges().listen((user) { ... }); listener automatically updates the UI whenever the user's authentication state changes (login, logout). The _signOut method handles logging out from Firebase and both social providers to ensure a complete logout.
Conclusion
Integrating social login with Google and Facebook into your Flutter application using Firebase Authentication provides a powerful, secure, and user-friendly way to authenticate users. By following these steps, you can offer your users a seamless sign-in experience, reduce friction, and focus on building great features for your app. Remember to thoroughly test your implementation on both Android and iOS devices to ensure all platform-specific configurations are correctly applied.