تسجيل الدخول الاجتماعي: Apple وFacebook وGitHub
تسجيل الدخول الاجتماعي: Apple وFacebook وGitHub
إضافة موفري تسجيل الدخول الاجتماعي تحسّن معدلات التحويل بشكل ملحوظ من خلال السماح للمستخدمين بالمصادقة باستخدام حسابات يثقون بها بالفعل. يغطي هذا الدرس دمج تسجيل الدخول عبر Apple (إلزامي لتطبيقات iOS التي تقدم أي تسجيل دخول من طرف ثالث)، وتسجيل الدخول عبر Facebook، وGitHub OAuth في مصادقة Firebase. لكل موفر متطلبات تهيئة خاصة بمنصته، لكنها جميعاً تتبع نفس النمط العام: الحصول على بيانات اعتماد OAuth من SDK الموفر، ثم تمريرها إلى Firebase لإنشاء حساب أو ربطه.
تسجيل الدخول عبر Apple
يستخدم تسجيل الدخول عبر Apple حزمة sign_in_with_apple على Flutter إلى جانب تدفق بيانات اعتماد firebase_auth. يتضمن الإعداد تغييرات في تهيئة Xcode وتغييرات في Firebase Console.
إعداد iOS / Xcode:
- في Xcode، افتح Signing & Capabilities وأضف ميزة Sign In with Apple.
- في Firebase Console، فعّل موفر Apple ضمن Authentication → Sign-in method وأدخل Services ID وTeam ID وKey ID والمفتاح الخاص (ملف .p8) من Apple Developer.
- سجّل Services ID في حساب Apple Developer الخاص بك وهيّئ
Return URLليشير إلى عنوان URL لإعادة توجيه OAuth في Firebase كما هو موضح في وحدة التحكم.
إعداد Android (اختياري لكن موصى به): يمر تسجيل الدخول عبر Apple على Android من خلال تدفق ويب. أضف URI إعادة التوجيه إلى Apple Services ID الخاص بك، وسجّل بصمة SHA-1 لتطبيق Android في Firebase.
تسجيل الدخول عبر Apple — تطبيق Flutter
import 'package:firebase_auth/firebase_auth.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import 'dart:convert';
import 'dart:math';
// توليد 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 للـ nonce (استيراد حزمة crypto)
// String _sha256ofString(String input) { ... }
Future<UserCredential?> signInWithApple() async {
final rawNonce = _generateNonce();
// final nonce = _sha256ofString(rawNonce); // تجزئة قبل الإرسال إلى Apple
try {
final appleCredential = await SignInWithApple.getAppleIDCredential(
scopes: [
AppleIDAuthorizationScopes.email,
AppleIDAuthorizationScopes.fullName,
],
// nonce: nonce, // تمرير الـ nonce المجزأ إلى Apple
);
final oauthCredential = OAuthProvider('apple.com').credential(
idToken: appleCredential.identityToken,
rawNonce: rawNonce, // تمرير الـ nonce الخام إلى Firebase
);
return await FirebaseAuth.instance.signInWithCredential(oauthCredential);
} on SignInWithAppleAuthorizationException catch (e) {
if (e.code == AuthorizationErrorCode.canceled) {
return null; // أغلق المستخدم النافذة
}
rethrow;
}
}
appleCredential.givenName وappleCredential.familyName فور أول تسجيل دخول — عمليات المصادقة اللاحقة ستُعيد null لهذه الحقول.تسجيل الدخول عبر Facebook
يستخدم تسجيل الدخول عبر Facebook الحزمة الرسمية flutter_facebook_auth. يجب إنشاء تطبيق Facebook في بوابة Meta for Developers وإدراج معرف الحزمة (iOS) واسم الحزمة + تجزئة المفتاح (Android) في القائمة البيضاء.
خطوات الإعداد:
- أضف تطبيقك إلى بوابة Meta للمطورين، واحصل على App ID وApp Secret.
- في Firebase Console، فعّل موفر Facebook وأدخل App ID وApp Secret.
- أضف
facebook_app_idوfacebook_client_tokenإلىAndroidManifest.xmlوInfo.plistكما تقتضي وثائق الحزمة. - لنظام Android، أنشئ تجزئة مفتاح الإصدار باستخدام
keytoolوأضفها إلى لوحة تحكم تطبيق Facebook ضمن Android → Key Hashes.
تسجيل الدخول عبر Facebook — تطبيق Flutter
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
Future<UserCredential?> signInWithFacebook() async {
// بدء تدفق تسجيل الدخول عبر Facebook
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: ${loginResult.message}');
}
// الحصول على رمز الوصول
final AccessToken accessToken = loginResult.accessToken!;
// إنشاء بيانات اعتماد Facebook لـ Firebase
final OAuthCredential facebookCredential =
FacebookAuthProvider.credential(accessToken.tokenString);
// تسجيل الدخول إلى Firebase ببيانات اعتماد Facebook
return FirebaseAuth.instance.signInWithCredential(facebookCredential);
}
// جلب بيانات الملف الشخصي (اختياري)
Future<Map<String, dynamic>> getFacebookUserData() async {
final userData = await FacebookAuth.instance.getUserData(
fields: 'name,email,picture.width(200)',
);
return userData;
}
GitHub OAuth
لا تمتلك GitHub حزمة Flutter مخصصة. بدلاً من ذلك، تستخدم GithubAuthProvider من Firebase مع تدفق OAuth عبر الويب، عادةً عبر signInWithPopup على الويب أو تدفق إعادة توجيه عبر رابط عميق على الهاتف المحمول.
خطوات الإعداد:
- سجّل OAuth App في إعدادات GitHub → Developer settings. اضبط Authorization Callback URL على عنوان URL لإعادة توجيه OAuth في Firebase.
- فعّل موفر GitHub في Firebase Console (Authentication → Sign-in method) وأدخل Client ID وClient Secret من GitHub.
- على الهاتف المحمول، استخدم
firebase_dynamic_linksأو مخطط URL مخصص للتعامل مع إعادة التوجيه إلى التطبيق بعد تفويض GitHub.
تسجيل الدخول عبر GitHub — باستخدام signInWithProvider (Flutter Web والهاتف المحمول)
import 'package:firebase_auth/firebase_auth.dart';
Future<UserCredential?> signInWithGitHub() async {
final githubProvider = GithubAuthProvider();
// طلب نطاقات إضافية عند الحاجة
githubProvider.addScope('read:user');
githubProvider.addScope('user:email');
try {
// على الويب: يفتح نافذة منبثقة؛ على الهاتف: يعيد التوجيه عبر المتصفح
final UserCredential credential =
await FirebaseAuth.instance.signInWithProvider(githubProvider);
return credential;
} on FirebaseAuthException catch (e) {
if (e.code == 'account-exists-with-different-credential') {
// التعامل مع ربط بيانات الاعتماد (انظر القسم أدناه)
await _linkGitHubToExistingAccount(e);
return null;
}
rethrow;
}
}
Future<void> _linkGitHubToExistingAccount(FirebaseAuthException e) async {
// جلب الموفرين المسجلين لهذا البريد الإلكتروني
final email = e.email!;
final methods = await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);
// طلب من المستخدم تسجيل الدخول بالموفر الموجود، ثم الربط
debugPrint('سجّل الدخول أولاً باستخدام: $methods، ثم اربط GitHub.');
}
ربط بيانات الاعتماد
قد يحاول مستخدم سبق له تسجيل الدخول بالبريد الإلكتروني وكلمة المرور تسجيل الدخول مرة أخرى عبر موفر اجتماعي يشترك في نفس البريد الإلكتروني. يُلقي Firebase خطأ account-exists-with-different-credential. الحل الصحيح هو:
- تسجيل دخول المستخدم باستخدام موفره الأصلي.
- استدعاء
user.linkWithCredential(pendingCredential)لإرفاق الموفر الاجتماعي الجديد بالحساب الموجود. - من تلك النقطة، يمكن للمستخدم تسجيل الدخول بأي من الطريقتين.
ملخص
في هذا الدرس تعلمت كيفية دمج ثلاثة موفري تسجيل دخول اجتماعي في تطبيق Flutter باستخدام مصادقة Firebase:
- تسجيل الدخول عبر Apple — إلزامي لتطبيقات iOS في App Store التي تقدم تسجيل دخول من طرف ثالث؛ يستخدم nonce آمناً، ويتطلب ميزة Xcode + تهيئة Firebase + Apple Developer Services ID.
- تسجيل الدخول عبر Facebook — يستخدم حزمة
flutter_facebook_auth؛ يتطلب تطبيق Meta Developer ومعرفات الحزمة وتجزئات المفاتيح وبيانات الاعتماد في Firebase Console. - GitHub OAuth — لا توجد SDK مخصصة؛ استخدم
GithubAuthProviderمعsignInWithProvider؛ يتطلب GitHub OAuth App وعنوان URL لـ callback مهيأ في Firebase.
تتبع الموفرات الثلاثة جميعها نفس نمط تسليم بيانات الاعتماد: الحصول على رمز الموفر، ولفّه في OAuthCredential من Firebase، ثم استدعاء signInWithCredential. تعامل مع خطأ account-exists-with-different-credential في كل مكان يُستخدم فيه تسجيل الدخول الاجتماعي لتجنب الحسابات المكررة.