Flutter & Firebase Auth: Implementing Google, Facebook, and Apple Social Login
In today's mobile-first world, user authentication is a cornerstone of almost every application. While traditional email and password methods are still prevalent, social login offers a streamlined, secure, and user-friendly alternative. This article will guide you through implementing Google, Facebook, and Apple social login in your Flutter application using Firebase Authentication, providing a robust and scalable authentication solution.
Why Flutter and Firebase Auth?
- Flutter: A UI toolkit for building natively compiled applications for mobile, web, and desktop from a single codebase. Its expressive UI and fast development cycle make it a top choice for modern app development.
- Firebase Authentication: A comprehensive authentication solution provided by Google. It supports various authentication methods, including email/password, phone, and popular social identity providers like Google, Facebook, and Apple. Firebase Auth handles the complexities of secure user management, allowing developers to focus on core application features.
Prerequisites
Before diving into the implementation, ensure you have the following:
- A Flutter development environment set up.
- A Firebase project created and configured.
- Basic understanding of Flutter and Dart.
- For Facebook login: A Facebook Developer account and a Facebook App configured.
- For Apple login: An Apple Developer account and an App ID configured with "Sign In with Apple" capability.
1. Firebase Project Setup
- Create/Open Firebase Project: Go to the Firebase Console, create a new project, or open an existing one.
- Enable Authentication Methods:
- Navigate to "Authentication" in the left sidebar.
- Go to the "Sign-in method" tab.
- Enable "Google", "Facebook", and "Apple" providers.
- For Facebook, you'll need to enter your Facebook App ID and App Secret (from your Facebook Developer account).
- For Apple, ensure you have registered your app with Apple and enabled "Sign In with Apple" capabilities. Firebase will usually require your Apple Team ID, which you can find in your Apple Developer account.
- Add Flutter Apps to Firebase:
- Add your Android and iOS apps to the Firebase project. Follow the on-screen instructions.
- For Android, register your package name and generate SHA-1 debug key (
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android). Downloadgoogle-services.jsonand place it in yourandroid/appdirectory. - For iOS, register your bundle ID. Download
GoogleService-Info.plistand place it in yourios/Runnerdirectory using Xcode (drag and drop, ensure "Copy items if needed" is checked).
2. Flutter Project Setup
- Create a New Flutter Project:
flutter create social_login_app cd social_login_app - Add Dependencies: Open your
pubspec.yamlfile and add the following dependencies:
Rundependencies: flutter: sdk: flutter firebase_core: ^2.24.2 firebase_auth: ^4.15.2 google_sign_in: ^6.1.6 flutter_facebook_auth: ^6.1.1 sign_in_with_apple: ^6.1.1 # For Apple loginflutter pub getto fetch the packages. - Initialize Firebase: In your
main.dart, initialize Firebase before running your app.import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); // Initialize Firebase runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Social Login Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const LoginPage(), ); } } class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override StatecreateState() => _LoginPageState(); } class _LoginPageState extends State { String _userStatus = 'Not logged in'; @override Widget build(BuildContext context) { return Scaffold( appB`ar: AppBar(title: const Text('Social Login')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(_userStatus), const SizedBox(height: 20), // Social login buttons will go here ], ), ), ); } }
3. Google Sign-In Implementation
Platform Configuration:
- Android: Ensure you've added your SHA-1 fingerprint to your Firebase Android app settings.
- iOS: In Xcode, go to your project target's "Info" tab. Under "URL Types", add a new URL Type. Set "Identifier" to your bundle ID, and "URL Schemes" to your REVERSED_CLIENT_ID (found in
GoogleService-Info.plist, e.g.,com.googleusercontent.apps.1234567890-abcdefg).
Flutter Code:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
Future<User?> signInWithGoogle() async {
try {
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
if (googleUser == null) return null; // User cancelled
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("Google sign-in error: $e");
return null;
}
}
Future<void> signOut() async {
await GoogleSignIn().signOut();
await _auth.signOut();
}
}
// In your LoginPage's _LoginPageState:
// ...
// In your build method:
// ...
ElevatedButton(
onPressed: () async {
setState(() => _userStatus = 'Signing in with Google...');
User? user = await AuthService().signInWithGoogle();
if (user != null) {
setState(() => _userStatus = 'Logged in as ${user.displayName}');
} else {
setState(() => _userStatus = 'Google sign-in failed or cancelled.');
}
},
child: const Text('Sign in with Google'),
),
// ...
4. Facebook Sign-In Implementation
Platform Configuration:
- Facebook Developer Console:
- Create a new app on Facebook for Developers.
- Add "Facebook Login" product to your app.
- Go to "Settings" -> "Basic" to get your App ID and App Secret (add these to Firebase Auth settings).
- Under "Facebook Login" -> "Settings", ensure "Client OAuth Login" and "Web OAuth Login" are enabled.
- Add platform-specific configurations (Android and iOS).
- Android:
- In
android/app/src/main/res/values/strings.xml, add:<string name="facebook_app_id">YOUR_FACEBOOK_APP_ID</string> <string name="fb_login_protocol_scheme">fbYOUR_FACEBOOK_APP_ID</string> <string name="facebook_client_token">YOUR_FACEBOOK_CLIENT_TOKEN</string> - In
android/app/src/main/AndroidManifest.xml, inside the<application>tag:<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"/> <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>
- In
- iOS:
- In
ios/Runner/Info.plist, add the following (replace with your actual App ID and Display Name):<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>fbYOUR_FACEBOOK_APP_ID</string> </array> </dict> </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-share-api</string> <string>fbauth2</string> <string>fbshareextension</string> </array> - In
ios/Runner/AppDelegate.swift(or .m if Objective-C), configure the Facebook SDK:// For Swift: import Flutter import UIKit import Firebase import FBSDKCoreKit // Add this @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { FirebaseApp.configure() // Ensure Firebase is configured ApplicationDelegate.shared.application( // Add this application, didFinishLaunchingWithOptions: launchOptions ) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } // Add this method to handle URL schemes for Facebook login override func application( _ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:] ) -> Bool { if ApplicationDelegate.shared.application(application, open: url, options: options) { return true } return super.application(application, open: url, options: options) } }
- In
Flutter Code:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
// In AuthService class:
// ...
Future<User?> signInWithFacebook() async {
try {
final LoginResult result = await FlutterFacebookAuth.instance.login();
if (result.status == LoginStatus.success) {
final AuthCredential credential = FacebookAuthProvider.credential(result.accessToken!.token);
final UserCredential userCredential = await _auth.signInWithCredential(credential);
return 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("Facebook sign-in error: $e");
return null;
}
}
// In signOut method:
// ...
Future<void> signOut() async {
await GoogleSignIn().signOut();
await FlutterFacebookAuth.instance.logOut(); // Add this
await _auth.signOut();
}
}
// In your LoginPage's _LoginPageState:
// ...
// In your build method:
// ...
ElevatedButton(
onPressed: () async {
setState(() => _userStatus = 'Signing in with Facebook...');
User? user = await AuthService().signInWithFacebook();
if (user != null) {
setState(() => _userStatus = 'Logged in as ${user.displayName}');
} else {
setState(() => _userStatus = 'Facebook sign-in failed or cancelled.');
}
},
child: const Text('Sign in with Facebook'),
),
// ...
5. Apple Sign-In Implementation
Sign In with Apple is only available on iOS devices running iOS 13.0+ and web (using Firebase Web SDK).
Platform Configuration:
- Apple Developer Account:
- Go to Apple Developer.
- Under "Certificates, IDs & Profiles" -> "Identifiers", select your App ID.
- Enable "Sign In with Apple" capability for your App ID.
- If you need web support, you must also create a "Services ID" and configure it for "Sign In with Apple" (not strictly required for Flutter mobile only).
- Xcode:
- Open your Flutter project in Xcode (
ios/Runner.xcworkspace). - Select your project target in the project navigator.
- Go to the "Signing & Capabilities" tab.
- Click "+ Capability" and add "Sign In with Apple".
- Ensure your Bundle ID matches the App ID registered with Apple and that automatic signing is set up or proper provisioning profiles are selected.
- Open your Flutter project in Xcode (
Flutter Code:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import 'dart:io' show Platform; // For platform specific checks
// In AuthService class:
// ...
Future<User?> signInWithApple() async {
if (Platform.isIOS) {
try {
final AuthorizationCredentialAppleID appleCredential =
await SignInWithApple.getAppleIDCredential(
scopes: [
AppleIDAuthorizationScopes.email,
AppleIDAuthorizationScopes.fullName,
],
);
final AuthCredential credential = AppleAuthProvider.credential(
accessToken: appleCredential.identityToken,
idToken: appleCredential.identityToken,
);
final UserCredential userCredential = await _auth.signInWithCredential(credential);
return userCredential.user;
} catch (e) {
print("Apple sign-in error: $e");
return null;
}
} else {
print("Sign In with Apple is only available on iOS.");
return null;
}
}
// In signOut method:
// ...
Future<void> signOut() async {
await GoogleSignIn().signOut();
await FlutterFacebookAuth.instance.logOut();
// No specific Apple logout needed beyond Firebase signOut
await _auth.signOut();
}
}
// In your LoginPage's _LoginPageState:
// ...
// In your build method:
// ...
if (Platform.isIOS) // Only show Apple sign-in on iOS
ElevatedButton(
onPressed: () async {
setState(() => _userStatus = 'Signing in with Apple...');
User? user = await AuthService().signInWithApple();
if (user != null) {
setState(() => _userStatus = 'Logged in as ${user.displayName ?? "Apple User"}');
} else {
setState(() => _userStatus = 'Apple sign-in failed or cancelled.');
}
},
child: const Text('Sign in with Apple'),
),
// ...
6. Complete LoginPage Example
import 'dart:io';
import 'package:flutter/material.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 'package:sign_in_with_apple/sign_in_with_apple.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
Future<User?> signInWithGoogle() 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,
);
final UserCredential userCredential = await _auth.signInWithCredential(credential);
return userCredential.user;
} catch (e) {
print("Google sign-in error: $e");
return null;
}
}
Future<User?> signInWithFacebook() async {
try {
final LoginResult result = await FlutterFacebookAuth.instance.login();
if (result.status == LoginStatus.success) {
final AuthCredential credential = FacebookAuthProvider.credential(result.accessToken!.token);
final UserCredential userCredential = await _auth.signInWithCredential(credential);
return 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("Facebook sign-in error: $e");
return null;
}
}
Future<User?> signInWithApple() async {
if (Platform.isIOS) { // Apple Sign-In is primarily for iOS
try {
final AuthorizationCredentialAppleID appleCredential =
await SignInWithApple.getAppleIDCredential(
scopes: [
AppleIDAuthorizationScopes.email,
AppleIDAuthorizationScopes.fullName,
],
);
final AuthCredential credential = AppleAuthProvider.credential(
accessToken: appleCredential.identityToken,
idToken: appleCredential.identityToken,
);
final UserCredential userCredential = await _auth.signInWithCredential(credential);
return userCredential.user;
} catch (e) {
print("Apple sign-in error: $e");
return null;
}
} else {
print("Sign In with Apple is only fully supported on iOS.");
// You could implement web-based Apple Sign-In for other platforms if needed
return null;
}
}
Future<void> signOut() async {
await GoogleSignIn().signOut();
await FlutterFacebookAuth.instance.logOut();
await _auth.signOut();
}
}
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State createState() => _LoginPageState();
}
class _LoginPageState extends State {
String _userStatus = 'Not logged in';
User? _currentUser;
@override
void initState() {
super.initState();
_checkCurrentUser();
}
void _checkCurrentUser() {
_currentUser = FirebaseAuth.instance.currentUser;
if (_currentUser != null) {
setState(() {
_userStatus = 'Logged in as ${_currentUser!.displayName ?? _currentUser!.email}';
});
}
}
void _updateUserStatus(User? user, String providerName) {
if (user != null) {
setState(() {
_currentUser = user;
_userStatus = 'Logged in as ${user.displayName ?? user.email ?? "$providerName User"}';
});
} else {
setState(() {
_userStatus = '$providerName sign-in failed or cancelled.';
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Social Login Demo')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(_userStatus),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
setState(() => _userStatus = 'Signing in with Google...');
User? user = await AuthService().signInWithGoogle();
_updateUserStatus(user, 'Google');
},
child: const Text('Sign in with Google'),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () async {
setState(() => _userStatus = 'Signing in with Facebook...');
User? user = await AuthService().signInWithFacebook();
_updateUserStatus(user, 'Facebook');
},
child: const Text('Sign in with Facebook'),
),
const SizedBox(height: 10),
if (Platform.isIOS) // Only show Apple sign-in on iOS
ElevatedButton(
onPressed: () async {
setState(() => _userStatus = 'Signing in with Apple...');
User? user = await AuthService().signInWithApple();
_updateUserStatus(user, 'Apple');
},
child: const Text('Sign in with Apple'),
),
const SizedBox(height: 20),
if (_currentUser != null)
ElevatedButton(
onPressed: () async {
await AuthService().signOut();
setState(() {
_currentUser = null;
_userStatus = 'Logged out';
});
},
child: const Text('Sign Out'),
),
],
),
),
);
}
}
Conclusion
Integrating social login with Flutter and Firebase Authentication provides a seamless and secure experience for your users. By following this guide, you've implemented Google, Facebook, and Apple sign-in, covering a significant portion of the global user base. Remember to thoroughly test each provider on both Android and iOS platforms to ensure all configurations are correct and working as expected.