Authentication & Security

Social Sign-In: Apple, Facebook & GitHub

16 min Lesson 4 of 12

Social Sign-In: Apple, Facebook & GitHub

Adding social sign-in providers dramatically improves conversion rates by letting users authenticate with accounts they already trust. This lesson covers integrating Apple Sign-In (mandatory for iOS apps that offer any third-party login), Facebook Login, and GitHub OAuth into Firebase Authentication. Each provider has unique platform configuration requirements, but they all follow the same high-level pattern: obtain an OAuth credential from the provider's SDK, then pass it to Firebase to create or link an account.

Note: Apple Sign-In is required by App Store Review Guidelines (rule 4.8) for any iOS app that offers third-party or social sign-in. Submitting an iOS app with Facebook or Google login but without Apple login will result in rejection.

Apple Sign-In

Apple Sign-In uses the sign_in_with_apple package on Flutter alongside the firebase_auth credential flow. The setup involves both Xcode configuration and Firebase Console changes.

iOS / Xcode setup:

  • In Xcode, open Signing & Capabilities and add the Sign In with Apple capability.
  • In the Firebase Console, enable the Apple provider under Authentication → Sign-in method and supply your Apple Services ID, Team ID, Key ID, and the private key (.p8 file) from Apple Developer.
  • Register a Services ID in your Apple Developer account and configure the Return URL to the Firebase OAuth redirect URL shown in the console.

Android setup (optional but recommended): Apple Sign-In on Android routes through a web-based flow. Add the redirect URI to your Apple Services ID, and register the SHA-1 fingerprint of your Android app in Firebase.

Apple Sign-In — Flutter implementation

import 'package:firebase_auth/firebase_auth.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import 'dart:convert';
import 'dart:math';

// Generate a cryptographically secure nonce
String _generateNonce([int length = 32]) {
  const charset =
      '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._';
  final random = Random.secure();
  return List.generate(length, (_) => charset[random.nextInt(charset.length)])
      .join();
}

// SHA-256 hash a nonce (import crypto package)
// String _sha256ofString(String input) { ... }

Future<UserCredential?> signInWithApple() async {
  final rawNonce = _generateNonce();
  // final nonce = _sha256ofString(rawNonce); // hash before sending to Apple

  try {
    final appleCredential = await SignInWithApple.getAppleIDCredential(
      scopes: [
        AppleIDAuthorizationScopes.email,
        AppleIDAuthorizationScopes.fullName,
      ],
      // nonce: nonce, // pass hashed nonce to Apple
    );

    final oauthCredential = OAuthProvider('apple.com').credential(
      idToken: appleCredential.identityToken,
      rawNonce: rawNonce, // pass RAW nonce to Firebase
    );

    return await FirebaseAuth.instance.signInWithCredential(oauthCredential);
  } on SignInWithAppleAuthorizationException catch (e) {
    if (e.code == AuthorizationErrorCode.canceled) {
      return null; // user dismissed the sheet
    }
    rethrow;
  }
}
Warning: Apple only returns the user's name and email on the very first sign-in. Store appleCredential.givenName and appleCredential.familyName immediately on first login — subsequent authentications return null for these fields.

Facebook Login

Facebook Login uses the official flutter_facebook_auth package. You must create a Facebook App in the Meta for Developers portal and whitelist your bundle ID (iOS) and package name + key hash (Android).

Setup steps:

  • Add your app to the Meta Developer Portal, get the App ID and App Secret.
  • In Firebase Console, enable the Facebook provider and paste in your App ID and App Secret.
  • Add the facebook_app_id and facebook_client_token to AndroidManifest.xml and Info.plist as required by the package docs.
  • For Android, generate the release key hash with keytool and add it to the Facebook App dashboard under Android → Key Hashes.

Facebook Sign-In — Flutter implementation

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';

Future<UserCredential?> signInWithFacebook() async {
  // Trigger the Facebook sign-in flow
  final LoginResult loginResult = await FacebookAuth.instance.login(
    permissions: ['email', 'public_profile'],
  );

  if (loginResult.status == LoginStatus.cancelled) {
    return null;
  }

  if (loginResult.status != LoginStatus.success) {
    throw Exception('Facebook login failed: ${loginResult.message}');
  }

  // Obtain the access token
  final AccessToken accessToken = loginResult.accessToken!;

  // Create a Facebook credential for Firebase
  final OAuthCredential facebookCredential =
      FacebookAuthProvider.credential(accessToken.tokenString);

  // Sign in to Firebase with the Facebook credential
  return FirebaseAuth.instance.signInWithCredential(facebookCredential);
}

// Fetch profile data (optional — Facebook returns basic profile via Firebase)
Future<Map<String, dynamic>> getFacebookUserData() async {
  final userData = await FacebookAuth.instance.getUserData(
    fields: 'name,email,picture.width(200)',
  );
  return userData;
}

GitHub OAuth

GitHub does not have a dedicated Flutter package. Instead, you use Firebase's GithubAuthProvider with a custom OAuth web flow, typically via signInWithPopup on web or a deep-link redirect flow on mobile.

Setup steps:

  • Register an OAuth App in GitHub Settings → Developer settings. Set the Authorization Callback URL to the Firebase OAuth redirect URL.
  • Enable the GitHub provider in Firebase Console (Authentication → Sign-in method) and paste your GitHub Client ID and Client Secret.
  • On mobile, use the firebase_dynamic_links or a custom URL scheme to handle the redirect back to the app after GitHub authorization.

GitHub Sign-In — using signInWithProvider (Flutter Web & mobile)

import 'package:firebase_auth/firebase_auth.dart';

Future<UserCredential?> signInWithGitHub() async {
  final githubProvider = GithubAuthProvider();

  // Request additional scopes if needed
  githubProvider.addScope('read:user');
  githubProvider.addScope('user:email');

  try {
    // On Web: opens a popup; on mobile: redirects through browser
    final UserCredential credential =
        await FirebaseAuth.instance.signInWithProvider(githubProvider);
    return credential;
  } on FirebaseAuthException catch (e) {
    if (e.code == 'account-exists-with-different-credential') {
      // Handle credential linking (see section below)
      await _linkGitHubToExistingAccount(e);
      return null;
    }
    rethrow;
  }
}

Future<void> _linkGitHubToExistingAccount(FirebaseAuthException e) async {
  // Fetch which providers are registered for this email
  final email = e.email!;
  final methods = await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);
  // Prompt user to sign in with existing provider, then link
  debugPrint('Sign in first with: $methods, then link GitHub.');
}

Credential Linking

A user who has previously signed in with email/password may try to sign in again with a social provider that shares the same email. Firebase throws account-exists-with-different-credential. The correct resolution is to:

  • Sign the user in with their original provider.
  • Call user.linkWithCredential(pendingCredential) to attach the new social provider to the existing account.
  • From that point on, the user can sign in with either method.
Tip: Enable Account Linking in the Firebase Console (Authentication → Settings → User account linking) to "Prevent creation of multiple accounts with the same email address." This way Firebase itself raises the linking error instead of silently creating a duplicate account.

Summary

In this lesson you learned how to integrate three social sign-in providers into a Flutter app using Firebase Authentication:

  • Apple Sign-In — mandatory for iOS App Store apps offering third-party login; uses a secure nonce, requires Xcode capability + Firebase configuration + Apple Developer Services ID.
  • Facebook Login — uses the flutter_facebook_auth package; requires a Meta Developer App, bundle IDs, key hashes, and credentials in Firebase Console.
  • GitHub OAuth — no dedicated SDK; use GithubAuthProvider with signInWithProvider; requires a GitHub OAuth App and the redirect callback URL configured in Firebase.

All three follow the same credential-handoff pattern: obtain a provider token, wrap it in a Firebase OAuthCredential, then call signInWithCredential. Handle the account-exists-with-different-credential error everywhere social sign-in is used to avoid duplicate accounts.