
FirebaseUI لنظام التشغيل SwiftUI هي مكتبة حديثة مصمّمة خصيصًا لنظام التشغيل SwiftUI ومستندة إلى Firebase Authentication، وتوفّر عمليات تسجيل دخول مُعدّة مسبقًا لتطبيقك.
تتضمّن FirebaseUI for SwiftUI المزايا التالية:
- واجهة مستخدم تلقائية ذات آراء مسبقة: أضِف مسار تسجيل دخول كاملاً باستخدام
AuthPickerView. - قابلة للتخصيص: يمكنك عرض الأزرار التلقائية في التنسيق الخاص بك، أو إنشاء تجربة مخصّصة بالكامل.
- ربط الحسابات المجهولة: يمكنك اختياريًا ترقية المستخدمين المجهولين بدلاً من استبدالهم.
- إدارة الحساب: مسارات مدمجة لعمليات الاشتراك واسترداد كلمة المرور وإدارة الحساب
- مقدّمو خدمات متعدّدون: البريد الإلكتروني/كلمة المرور، ورابط البريد الإلكتروني، والمصادقة عبر الهاتف، وApple وGoogle وFacebook وTwitter ومقدّمو خدمات OAuth2/OIDC العاديون
- ميزات المصادقة الحديثة: تتضمّن دعمًا مدمجًا للمصادقة المتعدّدة العوامل وواجهات برمجة تطبيقات async/await.
قبل البدء
أضِف Firebase إلى مشروع Apple. احرص على إكمال خطوات SwiftUI.
تأكَّد من أنّ تطبيقك يستهدف الإصدار iOS 17 أو إصدارًا أحدث.
تثبيت
يتم توفير FirebaseUI لـ SwiftUI كحزمة Swift. لتثبيت الحزمة في مشروع Xcode، اتّبِع الخطوات التالية:
في Xcode، انقر على ملف > إضافة موارد الاعتمادية للحزمة (File > Add Package Dependencies).
أدخِل عنوان URL للحزمة:
https://github.com/firebase/FirebaseUI-iOSفي قائمة قاعدة التبعية، اختَر حتى الإصدار الرئيسي التالي واضبط الحد الأدنى للإصدار على أحدث إصدار.
انقر على إضافة حزمة، ثم اختَر المكتبات التي تريد إضافتها إلى مشروعك.
المكتبة التالية مطلوبة دائمًا. ويتضمّن التبعيات الأساسية، بالإضافة إلى إمكانية تسجيل الدخول باستخدام عنوان البريد الإلكتروني وكلمة المرور وتسجيل الدخول باستخدام رابط البريد الإلكتروني.
FirebaseAuthSwiftUI
إذا كنت تريد توفير طرق أخرى لتسجيل الدخول، اختَر أيضًا واحدة أو أكثر من المكتبات التالية:
-
FirebaseAppleSwiftUI(تسجيل الدخول باستخدام حساب على Apple) FirebaseGoogleSwiftUI(تسجيل الدخول باستخدام حساب Google)-
FirebaseFacebookSwiftUI(تسجيل الدخول باستخدام Facebook) -
FirebasePhoneAuthSwiftUI(مصادقة الهاتف) FirebaseTwitterSwiftUI(تسجيل الدخول عبر Twitter)-
FirebaseOAuthSwiftUI(مقدّمو خدمات OAuth وOIDC العاديون، مثل GitHub وMicrosoft وYahoo)
انقر على إضافة حزمة لتثبيت المكتبات المحدّدة.
اضبط
AuthServiceفي FirebaseUI في أداة التهيئة الخاصة بالمستوى الأعلىViewومرِّر الخدمة إلى طرق العرض الفرعية باستخدام البيئة.import FirebaseAuthSwiftUI import SwiftUI struct ContentView: View { let authService: AuthService init() { let configuration = AuthConfiguration() authService = AuthService(configuration: configuration) .withEmailSignIn() // Or whatever sign-in methods you want to support. // See the next section. } var body: some View { AuthPickerView { // AuthPickerView (the prebuilt View) or a custom View. Text("Welcome to your app!") } .environment(authService) } }
إعداد طُرق تسجيل الدخول
تتطلّب كل طريقة من طرق تسجيل الدخول المتوافقة بعض خطوات الإعداد الإضافية. وسِّع الأقسام أدناه واتّبِع التعليمات لإعداد كل مقدّم خدمة على حدة.
عنوان البريد الإلكتروني وكلمة المرور
من قسم الأمان > المصادقة > طريقة تسجيل الدخول في وحدة تحكّم Firebase، فعِّل موفّر البريد الإلكتروني/كلمة المرور.
سجِّل موفِّر الخدمة في مثيل
AuthService:let authService = AuthService() .withEmailSignIn()
المصادقة باستخدام رابط يتم إرساله إلى البريد الإلكتروني
لاستخدام ميزة تسجيل الدخول من خلال رابط البريد الإلكتروني بدون كلمة مرور، اتّبِع الخطوات التالية:
من قسم الأمان > المصادقة > طريقة تسجيل الدخول في وحدة تحكّم Firebase، فعِّل البريد الإلكتروني/كلمة المرور، ثم فعِّل تسجيل الدخول باستخدام رابط البريد الإلكتروني. يُرجى العِلم أنّه يجب تفعيل تسجيل الدخول باستخدام البريد الإلكتروني أو كلمة المرور لاستخدام ميزة تسجيل الدخول باستخدام رابط البريد الإلكتروني.
أضِف نطاق الرابط إلى النطاقات المعتمَدة.
اضبط
ActionCodeSettings، ومرِّره إلىAuthConfiguration، وسجِّل موفّر الخدمة:let actionCodeSettings = ActionCodeSettings() actionCodeSettings.handleCodeInApp = true actionCodeSettings.url = URL(string: "https://yourapp.firebaseapp.com") guard let bundleID = Bundle.main.bundleIdentifier else { fatalError("Missing bundle identifier for email link authentication setup.") } actionCodeSettings.setIOSBundleID(bundleID) let configuration = AuthConfiguration( emailLinkSignInActionCodeSettings: actionCodeSettings ) let authService = AuthService(configuration: configuration) .withEmailLinkSignIn()في
AppDelegateنفسه الذي تستدعي فيهFirebaseApp.configure()، أضِف منطقًا إلى طريقةapplication(_:open:options:)التي تعرضtrueعندما يكون عنوان URL الذي تم فتحه هو رابط تسجيل دخول Firebase Authentication. تشير هذه المنطق إلى أنّ FirebaseUI قد تعامل مع الرابط، وبالتالي لا يجب أن تعالجه أي أدوات معالجة روابط أخرى.import FacebookCore import FirebaseAuth import UIKit class AppDelegate: NSObject, UIApplicationDelegate { func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { FirebaseApp.configure() return true } func application( _ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:] ) -> Bool { if Auth.auth().canHandle(url) { return true } return false } }إذا أنشأت طرق عرض مخصّصة، استخدِم
authService.handleSignInLink(url:)عندما يفتح الرابط تطبيقك.
Apple
لاستخدام ميزة "تسجيل الدخول باستخدام حساب على Apple"، اتّبِع الخطوات التالية:
إعداد ميزة "تسجيل الدخول باستخدام حساب على Apple":
- فعِّل ميزة "تسجيل الدخول باستخدام Apple" لتطبيقك على صفحة الشهادات والمعرّفات وملفات التعريف في موقع المطوّرين الإلكتروني الخاص بشركة Apple.
- اربط موقعك الإلكتروني بتطبيقك كما هو موضّح في القسم الأول من مقالة إعداد ميزة "تسجيل الدخول باستخدام Apple" على الويب. عندما يُطلب منك ذلك، سجِّل عنوان URL التالي كعنوان URL للرجوع:
يمكنك الحصول على رقم تعريف مشروعك على Firebase من صفحة إعدادات وحدة تحكّم Firebase. عند الانتهاء، سجِّل معرّف الخدمة الجديد الذي ستحتاج إليه في القسم التالي.https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
- إنشاء مفتاح خاص لخدمة "تسجيل الدخول باستخدام Apple" ستحتاج إلى المفتاح الخاص الجديد ورقم تعريف المفتاح في القسم التالي.
- إذا كنت تستخدم أيًا من ميزات Firebase Authentication التي ترسل رسائل إلكترونية إلى المستخدمين، بما في ذلك تسجيل الدخول باستخدام رابط البريد الإلكتروني وإثبات ملكية عنوان البريد الإلكتروني وإلغاء تغيير الحساب وغيرها، عليك ضبط خدمة ترحيل البريد الإلكتروني الخاص من Apple وتسجيل
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com(أو نطاق نموذج البريد الإلكتروني المخصّص) حتى تتمكّن Apple من ترحيل الرسائل الإلكترونية التي ترسلها Firebase Authentication إلى عناوين بريد إلكتروني مجهولة الهوية من Apple.
من قسم الأمان > المصادقة > طريقة تسجيل الدخول في وحدة تحكّم Firebase، فعِّل Apple.
- حدِّد معرّف الخدمة الذي أنشأته في القسم السابق.
- في قسم إعدادات مسار رمز OAuth، حدِّد رقم تعريف فريق Apple والمفتاح الخاص ورقم تعريف المفتاح اللذين أنشأتهما في القسم السابق.
في Xcode، افتح قسم التوقيع والقدرات في أداة تعديل المشروع وأضِف قدرة تسجيل الدخول باستخدام Apple.
سجِّل موفِّر الخدمة في مثيل
AuthService:let authService = AuthService() .withAppleSignIn()
لاستخدام ميزة "تسجيل الدخول باستخدام حساب Google"، اتّبِع الخطوات التالية:
من قسم الأمان > المصادقة > طريقة تسجيل الدخول في وحدة تحكّم Firebase، فعِّل موفّر Google.
نزِّل نسخة جديدة من ملف
GoogleService-Info.plistالخاص بمشروعك وانسخه إلى مشروع Xcode. استبدال أي إصدارات حالية بالإصدار الجديدأضِف مخططات عناوين URL المخصّصة إلى مشروع Xcode:
افتح إعدادات مشروعك: انقر على اسم المشروع في عرض الشجرة على يمين الصفحة. اختَر تطبيقك من قسم الاستهدافات، ثم انقر على علامة التبويب المعلومات، ووسِّع قسم أنواع عناوين URL.
انقر على الزر +، وأضِف مخطط عنوان URL لمعرّف العميل المعكوس. للعثور على هذه القيمة، افتح ملف الإعدادات
وابحث عن المفتاحGoogleService-Info.plist REVERSED_CLIENT_ID. انسخ قيمة هذا المفتاح، والصِقها في مربّع مخططات عناوين URL في صفحة الإعدادات. لا تُجري أي تغييرات على الحقول الأخرى.عند الانتهاء، من المفترض أن يبدو الإعداد مشابهًا لما يلي (ولكن مع القيم الخاصة بتطبيقك):

سجِّل موفِّر الخدمة في مثيل
AuthService:let authService = AuthService() .withGoogleSignIn()
لاستخدام ميزة "تسجيل الدخول عبر Facebook"، اتّبِع الخطوات التالية:
يمكنك إعداد حزمة تطوير البرامج (SDK) الخاصة بميزة "تسجيل الدخول باستخدام Facebook" على أجهزة iOS باتّباع التعليمات الواردة على موقع Meta للمطوّرين. تخطَّ الخطوة الأخيرة، "إضافة ميزة تسجيل الدخول باستخدام Facebook إلى الرمز الخاص بك".
من قسم الأمان > المصادقة > طريقة تسجيل الدخول في وحدة تحكّم Firebase، فعِّل موفّر Facebook. ستحتاج إلى رقم تعريف تطبيق Facebook ورمز التطبيق السري من موقع Meta for Developers الإلكتروني.
سجِّل موفِّر الخدمة في مثيل
AuthService:let authService = AuthService() .withFacebookSignIn()
رقم الهاتف
لاستخدام مصادقة الهاتف، اتّبِع الخطوات التالية:
من قسم الأمان > المصادقة > طريقة تسجيل الدخول في Firebase console، فعِّل موفّر الهاتف.
اضبط إعدادات APNs لتطبيقك وفقًا للتعليمات الواردة في قسم بدء تلقّي الإشعارات الصامتة.
أضِف مخططات عناوين URL المخصّصة إلى مشروع Xcode:
افتح إعدادات مشروعك: انقر على اسم المشروع في عرض الشجرة على يمين الصفحة. اختَر تطبيقك من قسم الاستهدافات، ثم انقر على علامة التبويب المعلومات، ووسِّع قسم أنواع عناوين URL.
انقر على الزر +، وأضِف رقم تعريف التطبيق المرمّز كنمط عنوان URL. للعثور على هذه القيمة، افتح الإعدادات > الإعدادات العامة في وحدة تحكّم Firebase.
عند الانتهاء، من المفترض أن يبدو الإعداد مشابهًا لما يلي (ولكن مع القيم الخاصة بتطبيقك):

في
AppDelegateنفسه الذي تستدعي فيهFirebaseApp.configure()، أضِف معالجات الرموز المميزة لخدمة APNs:import FacebookCore import FirebaseAuth import UIKit class AppDelegate: NSObject, UIApplicationDelegate { func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { FirebaseApp.configure() return true } func application( _ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data ) { #if DEBUG Auth.auth().setAPNSToken(deviceToken, type: .sandbox) #else Auth.auth().setAPNSToken(deviceToken, type: .prod) #endif } }سجِّل موفِّر الخدمة في مثيل
AuthService:let authService = AuthService() .withPhoneSignIn()
Twitter (X)
لاستخدام ميزة "تسجيل الدخول عبر Twitter"، اتّبِع الخطوات التالية:
يمكنك إنشاء بيانات اعتماد X API باتّباع التعليمات على موقع X Developers الإلكتروني.
من قسم الأمان > المصادقة > طريقة تسجيل الدخول في Firebase Console، فعِّل موفّر Twitter. ستحتاج إلى مفتاح واجهة برمجة التطبيقات وسرّ واجهة برمجة التطبيقات من X Developer Console.
سجِّل موفِّر الخدمة في مثيل
AuthService:let authService = AuthService() .withTwitterSignIn()
موفّرو OAuth2 وOIDC العاديون
تتوافق FirebaseUI أيضًا مع موفّري OAuth المضمّنين، مثل GitHub وMicrosoft وYahoo، بالإضافة إلى موفّري OIDC المخصّصين الذين تم إعدادهم في Firebase Authentication.
let authService = AuthService()
.withOAuthSignIn(OAuthProviderSwift.github())
.withOAuthSignIn(OAuthProviderSwift.microsoft())
.withOAuthSignIn(OAuthProviderSwift.yahoo())
بالنسبة إلى موفّري OIDC المخصّصين، عليك ضبط إعدادات الموفّر أولاً في خدمة
Firebase Authentication، ثم إنشاء OAuthProviderSwift باستخدام معرّف الموفّر وإعدادات الزر:
let lineProvider = OAuthProviderSwift(
providerId: "oidc.line",
buttonLabel: "Sign in with LINE",
displayName: "LINE",
iconSystemName: "person.crop.circle.badge.checkmark",
buttonBackgroundColor: .green,
buttonForegroundColor: .white
)
let authService = AuthService()
.withOAuthSignIn(lineProvider)
استخدام طريقة عرض المصادقة المُنشأة مسبقًا
توفّر FirebaseUI لـ SwiftUI واجهة مستخدم مسبقة الإنشاء للمصادقة AuthPickerView، وهي واجهة مستخدم للمصادقة تتضمّن آراء مسبقة وتتعامل مع عملية المصادقة بأكملها نيابةً عنك. وهذه هي أسهل طريقة لإضافة مصادقة إلى تطبيقك.
مثال
في ما يلي مثال على استخدام AuthPickerView مع عدة موفّري خدمات وخيارات إعداد:
import FirebaseAppleSwiftUI
import FirebaseAuthSwiftUI
import FirebaseGoogleSwiftUI
import SwiftUI
struct ContentView: View {
let authService: AuthService
init() {
// Create configuration with options
let configuration = AuthConfiguration(
tosUrl: URL(string: "https://example.com/tos"),
privacyPolicyUrl: URL(string: "https://example.com/privacy"),
shouldAutoUpgradeAnonymousUsers: true
)
// Initialize AuthService with multiple providers
authService = AuthService(configuration: configuration)
.withEmailSignIn()
.withAppleSignIn()
.withGoogleSignIn()
}
var body: some View {
AuthPickerView {
authenticatedContent
}
.environment(authService)
}
var authenticatedContent: some View {
NavigationStack {
VStack(spacing: 20) {
if authService.authenticationState == .authenticated {
Text("Authenticated")
Button("Manage Account") {
authService.isPresented = true
}
.buttonStyle(.bordered)
Button("Sign Out") {
Task {
try? await authService.signOut()
}
}
.buttonStyle(.borderedProminent)
} else {
Text("Not Authenticated")
Button("Sign In") {
authService.isPresented = true
}
.buttonStyle(.borderedProminent)
}
}
.navigationTitle("My App")
}
.onChange(of: authService.authenticationState) { _, newValue in
// Automatically show auth UI when not authenticated
if newValue != .authenticating {
authService.isPresented = (newValue == .unauthenticated)
}
}
}
}
التخصيص النموذجي
على الرغم من أنّ جميع مَعلمات AuthConfiguration اختيارية، إلا أنّ معظم التطبيقات تخصّص الإعدادات التالية كحد أدنى:
let configuration = AuthConfiguration(
logo: ImageResource.exampleLogoAsset,
customStringsBundle: .main,
tosUrl: URL(string: "https://example.com/tos"),
privacyPolicyUrl: URL(string: "https://example.com/privacy"),
)
logo: صورة الشعار المعروضة في ورقة المصادقة للحصول على معلومات حول تضمين مادة عرض صورة خاصة بك، يُرجى الاطّلاع على إضافة صور إلى مشروع Xcode.
customStringsBundle: استخدِم السلاسل المخصّصة من الحزمة المحدّدة. يتم استخدام هذا الحقل في عملية الترجمة، ولكن أيضًا لتخصيص السلاسل التلقائية التي يستخدمهاAuthPickerView. على سبيل المثال، لضبط الرسالة المعروضة في أعلى ورقة المصادقة، أنشئLocalizable.stringsمع المحتوى التالي:"Sign in with Firebase" = "Sign in to use ExampleApp";
الميزات المضمّنة في العرض المُعدّ مسبقًا
عند استخدام AuthPickerView، ستحصل على ما يلي:
- عرض ورقة: تظهر واجهة مستخدم المصادقة كورقة مشروطة
- التنقّل المضمّن: التنقّل التلقائي بين شاشات تسجيل الدخول واسترداد كلمة المرور والمصادقة المتعددة العوامل ورابط البريد الإلكتروني والتحقّق من رقم الهاتف
- إدارة حالة المصادقة: يتم التبديل تلقائيًا بين واجهة مستخدم المصادقة والمحتوى استنادًا إلى
authService.authenticationState - التحكّم من خلال
isPresented: يمكنك التحكّم في وقت ظهور ورقة المصادقة من خلال ضبطauthService.isPresented = true/false
السلوكيات المحدّدة
تتضمّن قيمة AuthPickerView التلقائية آراءً حول كيفية التعامل مع عدة سيناريوهات معقّدة:
1. حلّ تعارضات الحسابات
عند حدوث تعارض في الحساب (على سبيل المثال، تسجيل الدخول باستخدام بيانات اعتماد مرتبطة بحساب آخر)، تتولّى خدمة AuthPickerView التعامل مع هذا التعارض تلقائيًا:
- تعارضات الترقية بدون تسجيل الدخول: في حال تفعيل
shouldAutoUpgradeAnonymousUsersوحدوث تعارض أثناء الترقية بدون تسجيل الدخول، يسجّل النظام تلقائيًا خروج المستخدم الذي لم يسجّل الدخول ويسجّل الدخول باستخدام بيانات الاعتماد الجديدة. - تعارضات أخرى: في حال حدوث تعارضات في بيانات الاعتماد بين حسابات غير مجهولة الهوية، يخزّن النظام بيانات الاعتماد المعلّقة ويحاول ربطها بعد تسجيل الدخول بنجاح.
يتم التعامل مع ذلك من خلال AccountConflictModifier المطبَّق على مستوى NavigationStack.
2. المصادقة المتعدّدة العوامل (MFA)
عند تفعيل المصادقة المتعدّدة العوامل في إعداداتك:
- رصد ما إذا كان يجب استخدام المصادقة المتعددة العوامل أثناء تسجيل الدخول
- عرض شاشات حلّ المصادقة المتعدّدة العوامل المناسبة (الرسائل القصيرة أو كلمة المرور المؤقتة لمرة واحدة)
- يتعامل مع عمليات التسجيل والإدارة في المصادقة المتعددة العوامل
- تتيح استخدام عوامل المصادقة المستندة إلى الرسائل القصيرة وكلمة المرور الصالحة لمرة واحدة المستندة إلى الوقت (TOTP)
3. معالجة الأخطاء
تتضمّن طرق العرض التلقائية معالجة مدمجة للأخطاء:
- عرض رسائل خطأ سهلة الاستخدام في مربّعات حوار التنبيه
- تستبعد تلقائيًا الأخطاء التي يتم التعامل معها داخليًا (مثل أخطاء الإلغاء، والتعارضات التي يتم التعامل معها تلقائيًا)
- استخدام رسائل الخطأ المترجمة عبر
StringUtils - يتم نشر الأخطاء من خلال مفتاح بيئة
reportError
4. تسجيل الدخول باستخدام رابط يصلك عبر البريد الإلكتروني
عند إعداد ميزة تسجيل الدخول باستخدام رابط يتم إرساله إلى البريد الإلكتروني:
- يخزّن عنوان البريد الإلكتروني تلقائيًا في مساحة تخزين التطبيق
- يتعامل مع التنقّل عبر الروابط لصفحات معيّنة من البريد الإلكتروني
- إدارة عملية تأكيد عنوان البريد الإلكتروني بالكامل
- يتيح ترقية حسابات المستخدمين المجهولين من خلال رابط في رسالة إلكترونية
5- الترقية التلقائية للمستخدمين المجهولين
عندما يكون shouldAutoUpgradeAnonymousUsers مفعّلاً:
- محاولة ربط الحسابات المجهولة تلقائيًا ببيانات اعتماد تسجيل الدخول الجديدة
- الاحتفاظ ببيانات المستخدم من خلال الترقية بدلاً من استبدال الجلسات المجهولة
- التعامل مع تعارضات الترقية بسلاسة
6. إعادة المصادقة في طرق العرض التلقائية
تتطلّب العمليات الحسّاسة، مثل حذف الحسابات أو تعديل كلمات المرور أو إلغاء تسجيل عوامل المصادقة المتعدّدة، إجراء مصادقة حديثة. عند استخدام طرق العرض التلقائية، تتم إعادة المصادقة تلقائيًا استنادًا إلى مزوّد خدمة تسجيل الدخول الذي يستخدمه المستخدم.
عندما تتطلّب عملية حسّاسة إعادة المصادقة، يتم تلقائيًا ما يلي في طرق العرض التلقائية:
مقدّمو خدمة OAuth (مثل Google وApple وFacebook وTwitter وما إلى ذلك): اعرض تنبيهًا يطلب من المستخدم تأكيد العملية، ثم احصل تلقائيًا على بيانات اعتماد جديدة وأكمِل العملية.
البريد الإلكتروني/كلمة المرور: عرض ورقة تطلب من المستخدم إدخال كلمة المرور قبل المتابعة
رابط البريد الإلكتروني: عرض تنبيه يطلب إرسال رسالة إلكترونية لتأكيد الحساب، ثم عرض ورقة تتضمّن تعليمات للتحقّق من البريد الإلكتروني ينقر المستخدم على الرابط في رسالته الإلكترونية لإكمال عملية إعادة المصادقة.
الهاتف: عرض تنبيه يوضّح أنّه يجب إثبات ملكية الهاتف، ثم عرض ورقة لإثبات ملكية الهاتف باستخدام رمز SMS
تتم إعادة محاولة العملية تلقائيًا بعد إعادة المصادقة بنجاح. لا يلزم توفير رمز إضافي عند استخدام AuthPickerView أو طرق عرض إدارة الحساب المضمّنة (UpdatePasswordView وSignedInView وما إلى ذلك).
إعدادات متقدّمة: إنشاء طرق عرض مصادقة مخصّصة
إذا كنت بحاجة إلى المزيد من التحكّم في واجهة المستخدم أو مسار التنقّل، يمكنك إنشاء طرق عرض مصادقة مخصّصة مع الاستفادة من AuthService لمنطق المصادقة.
يمكنك دمج عناصر FirebaseUI مع منطق مخصّص بعدة طرق. تحتوي الأقسام التالية على أمثلة لبعض طرق التخصيص التي يمكنك استخدامها.
الطريقة 1: أزرار مخصّصة مع registerProvider()
للحصول على تحكّم كامل في مظهر الزر، يمكنك إنشاء عملية تنفيذ AuthProviderUI مخصّصة خاصة بك تتضمّن أي موفّر وتعرض طريقة عرض الزر المخصّص.
إنشاء واجهة مستخدم مخصّصة لمقدّم الخدمة
في ما يلي كيفية إنشاء زر مخصّص على Twitter كمثال:
import FirebaseAuthSwiftUI
import FirebaseTwitterSwiftUI
import SwiftUI
// Step 1: Create your custom button view
struct CustomTwitterButton: View {
let provider: TwitterProviderSwift
@Environment(AuthService.self) private var authService
@Environment(\.mfaHandler) private var mfaHandler
var body: some View {
Button {
Task {
do {
let outcome = try await authService.signIn(provider)
// Handle MFA if required
if case let .mfaRequired(mfaInfo) = outcome,
let onMFA = mfaHandler {
onMFA(mfaInfo)
}
} catch {
// Do Something Else
}
}
} label: {
HStack { // Your custom icon
Text("Sign in with Twitter")
.fontWeight(.semibold)
}
.frame(maxWidth: .infinity)
.padding()
.background(
LinearGradient(
colors: [Color.blue, Color.cyan],
startPoint: .leading,
endPoint: .trailing
)
)
.foregroundColor(.white)
.cornerRadius(12)
.shadow(radius: 4)
}
}
}
// Step 2: Create a custom AuthProviderUI wrapper
class CustomTwitterProviderAuthUI: AuthProviderUI {
private let typedProvider: TwitterProviderSwift
var provider: AuthProviderSwift { typedProvider }
let id: String = "twitter.com"
init(provider: TwitterProviderSwift = TwitterProviderSwift()) {
typedProvider = provider
}
@MainActor func authButton() -> AnyView {
AnyView(CustomTwitterButton(provider: typedProvider))
}
}
// Step 3: Use it in your app
struct ContentView: View {
let authService: AuthService
init() {
let configuration = AuthConfiguration()
authService = AuthService(configuration: configuration)
// Register your custom provider UI
authService.registerProvider(
providerWithButton: CustomTwitterProviderAuthUI()
)
authService.isPresented = true
}
var body: some View {
AuthPickerView {
usersApp
}
.environment(authService)
}
var usersApp: some View {
NavigationStack {
VStack {
Button {
authService.isPresented = true
} label: {
Text("Authenticate")
}
}
}
}
}
مثال على زر مخصّص مبسط
يمكنك أيضًا إنشاء أزرار مخصّصة أبسط لأي مقدّم خدمة:
import FirebaseAuthSwiftUI
import FirebaseGoogleSwiftUI
import FirebaseAppleSwiftUI
import SwiftUI
// Custom Google Provider UI
class CustomGoogleProviderAuthUI: AuthProviderUI {
private let typedProvider: GoogleProviderSwift
var provider: AuthProviderSwift { typedProvider }
let id: String = "google.com"
init() {
typedProvider = GoogleProviderSwift()
}
@MainActor func authButton() -> AnyView {
AnyView(CustomGoogleButton(provider: typedProvider))
}
}
struct CustomGoogleButton: View {
let provider: GoogleProviderSwift
@Environment(AuthService.self) private var authService
var body: some View {
Button {
Task {
try? await authService.signIn(provider)
}
} label: {
HStack {
Image(systemName: "g.circle.fill")
Text("My Custom Google Button")
}
.frame(maxWidth: .infinity)
.padding()
.background(Color.purple) // Your custom color
.foregroundColor(.white)
.cornerRadius(10)
}
}
}
// Then use it
struct ContentView: View {
let authService: AuthService
init() {
let configuration = AuthConfiguration()
authService = AuthService(configuration: configuration)
.withAppleSignIn() // Use default Apple button
// Use custom Google button
authService.registerProvider(
providerWithButton: CustomGoogleProviderAuthUI()
)
}
var body: some View {
AuthPickerView {
Text("App Content")
}
.environment(authService)
}
}
تعمل هذه الطريقة مع جميع موفّري الخدمات: Google وApple وTwitter وFacebook والهاتف وموفّرو خدمات OAuth. ما عليك سوى إنشاء طريقة عرض الزر المخصّص وتضمينها في فئة متوافقة مع AuthProviderUI.
الطريقة 2: الأزرار التلقائية مع طرق عرض مخصّصة
يمكنك استخدام AuthService.renderButtons() وتخطّي AuthPickerView لعرض أزرار المصادقة التلقائية مع توفير التنسيق والتنقّل الخاصَّين بك:
import FirebaseAuthSwiftUI
import FirebaseGoogleSwiftUI
import FirebaseAppleSwiftUI
import SwiftUI
struct CustomAuthView: View {
@Environment(AuthService.self) private var authService
var body: some View {
VStack(spacing: 30) {
// Your custom logo/branding
Image("app-logo")
.resizable()
.frame(width: 150, height: 150)
Text("Welcome to My App")
.font(.largeTitle)
.fontWeight(.bold)
Text("Sign in to continue")
.font(.subheadline)
.foregroundStyle(.secondary)
// Render default auth buttons
authService.renderButtons(spacing: 12)
.padding()
}
.padding()
}
}
struct ContentView: View {
init() {
let configuration = AuthConfiguration()
authService = AuthService(configuration: configuration)
.withGoogleSignIn()
.withAppleSignIn()
}
let authService: AuthService
var body: some View {
NavigationStack {
if authService.authenticationState == .authenticated {
Text("Authenticated!")
} else {
CustomAuthView()
}
}
.environment(authService)
}
}
الطريقة 3: طرق عرض مخصّصة مع عناصر تنقّل مخصّصة
للتحكّم الكامل في المسار بأكمله، يمكنك تخطّي AuthPickerView وإنشاء نظام التنقّل الخاص بك:
import FirebaseAuth
import FirebaseAuthSwiftUI
import FirebaseGoogleSwiftUI
import SwiftUI
enum CustomAuthRoute {
case signIn
case phoneVerification
case mfaResolution
}
struct ContentView: View {
private let authService: AuthService
@State private var navigationPath: [CustomAuthRoute] = []
@State private var errorMessage: String?
init() {
let configuration = AuthConfiguration()
self.authService = AuthService(configuration: configuration)
.withGoogleSignIn()
.withPhoneSignIn()
}
var body: some View {
NavigationStack(path: $navigationPath) {
Group {
if authService.authenticationState == .authenticated {
authenticatedView
} else {
customSignInView
}
}
.navigationDestination(for: CustomAuthRoute.self) { route in
switch route {
case .signIn:
customSignInView
case .phoneVerification:
customPhoneVerificationView
case .mfaResolution:
customMFAView
}
}
}
.environment(authService)
.alert("Error", isPresented: .constant(errorMessage != nil)) {
Button("OK") {
errorMessage = nil
}
} message: {
Text(errorMessage ?? "")
}
}
var customSignInView: some View {
VStack(spacing: 20) {
Text("Custom Sign In")
.font(.title)
Button("Sign in with Google") {
Task {
do {
let provider = GoogleProviderSwift(clientID: Auth.auth().app?.options.clientID ?? "")
let outcome = try await authService.signIn(provider)
// Handle MFA if required
if case .mfaRequired = outcome {
navigationPath.append(.mfaResolution)
}
} catch {
errorMessage = error.localizedDescription
}
}
}
.buttonStyle(.borderedProminent)
Button("Phone Sign In") {
navigationPath.append(.phoneVerification)
}
.buttonStyle(.bordered)
}
.padding()
}
var customPhoneVerificationView: some View {
Text("Custom Phone Verification View")
// Implement your custom phone auth UI here
}
var customMFAView: some View {
Text("Custom MFA Resolution View")
// Implement your custom MFA UI here
}
var authenticatedView: some View {
VStack(spacing: 20) {
Text("Welcome!")
Text("Email: \(authService.currentUser?.email ?? "N/A")")
Button("Sign Out") {
Task {
try? await authService.signOut()
}
}
.buttonStyle(.borderedProminent)
}
}
}
اعتبارات مهمة لطرق العرض المخصّصة
عند إنشاء طرق عرض مخصّصة، عليك التعامل مع عدة أمور بنفسك، بينما يتعامل AuthPickerView معها تلقائيًا:
- تعارضات الحسابات: يمكنك تنفيذ استراتيجية حلّ التعارضات الخاصة بك باستخدام
AuthServiceError.accountConflict - التعامل مع المصادقة المتعدّدة العوامل: تحقَّق من
SignInOutcomeبحثًا عن.mfaRequiredوتعامل مع حلّ المصادقة المتعدّدة العوامل يدويًا. - ترقية المستخدمين المجهولين: التعامل مع ربط الحسابات المجهولة في حال تفعيل
shouldAutoUpgradeAnonymousUsers - حالة التنقّل: إدارة التنقّل بين شاشات المصادقة المختلفة (تأكيد رقم الهاتف واسترداد كلمة المرور وما إلى ذلك)
- حالات التحميل: عرض مؤشرات التحميل أثناء عمليات المصادقة غير المتزامنة من خلال مراقبة
authService.authenticationState - إعادة المصادقة: التعامل مع أخطاء إعادة المصادقة للعمليات الحسّاسة (راجِع إعادة المصادقة في طرق العرض المخصّصة أدناه)
إعادة المصادقة في طرق العرض المخصّصة
عند إنشاء عروض مخصّصة، تعامَل مع إعادة المصادقة من خلال رصد أخطاء معيّنة وتنفيذ مسار خاص بك. تؤدي العمليات الحسّاسة إلى ظهور أربعة أنواع من أخطاء إعادة المصادقة، ويحتوي كل منها على معلومات السياق.
أنماط التنفيذ
مقدّمو خدمات OAuth (مثل Google وApple وFacebook وTwitter وما إلى ذلك):
يمكنك رصد الخطأ واستدعاء reauthenticate(context:) التي تعالج تلقائيًا عملية OAuth:
do {
try await authService.deleteUser()
} catch let error as AuthServiceError {
if case .oauthReauthenticationRequired(let context) = error {
try await authService.reauthenticate(context: context)
try await authService.deleteUser() // Retry operation
}
}
البريد الإلكتروني/كلمة المرور:
التقط الخطأ واطلب كلمة المرور وأنشئ بيانات الاعتماد واستدعِ reauthenticate(with:):
do {
try await authService.updatePassword(to: newPassword)
} catch let error as AuthServiceError {
if case .emailReauthenticationRequired(let context) = error {
// Show your password prompt UI
let password = await promptUserForPassword()
let credential = EmailAuthProvider.credential(
withEmail: context.email,
password: password
)
try await authService.reauthenticate(with: credential)
try await authService.updatePassword(to: newPassword) // Retry
}
}
الهاتف:
التقط الخطأ وأثبِت ملكية الهاتف وأنشئ بيانات الاعتماد واتّصِل بـ reauthenticate(with:):
do {
try await authService.deleteUser()
} catch let error as AuthServiceError {
if case .phoneReauthenticationRequired(let context) = error {
// Send verification code
let verificationId = try await authService.verifyPhoneNumber(
phoneNumber: context.phoneNumber
)
// Show your SMS code input UI
let code = await promptUserForSMSCode()
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationId,
verificationCode: code
)
try await authService.reauthenticate(with: credential)
try await authService.deleteUser() // Retry
}
}
رابط البريد الإلكتروني:
التقط الخطأ وأرسِل رسالة تأكيد إلكترونية وتعامل مع عنوان URL الوارد:
do {
try await authService.updatePassword(to: newPassword)
} catch let error as AuthServiceError {
if case .emailLinkReauthenticationRequired(let context) = error {
// Send verification email
try await authService.sendEmailSignInLink(
email: context.email,
isReauth: true
)
// Show your "Check your email" UI
await showCheckEmailUI()
// When user taps the link, it opens your app with a URL
// Handle it in your URL handler:
// try await authService.handleSignInLink(url: url)
// The handleSignInLink method automatically completes reauthentication
try await authService.updatePassword(to: newPassword) // Retry
}
}
تتضمّن جميع عناصر سياق إعادة المصادقة السمة .displayMessage للنص المعروض للمستخدم.
موفّرو OAuth مخصّصون
يمكنك إنشاء موفّري OAuth مخصّصين لخدمات تتجاوز الخدمات المضمّنة:
⚠️ ملاحظة مهمة: يجب إعداد موفّري خدمة OIDC (اتصال OpenID) في إعدادات "المصادقة" في مشروعك على Firebase قبل استخدامهم. في "وحدة تحكّم Firebase"، انتقِل إلى المصادقة → طريقة تسجيل الدخول وأضِف موفِّر OIDC باستخدام بيانات الاعتماد المطلوبة (معرّف العميل وسر العميل وعنوان URL الخاص بجهة الإصدار). يجب أيضًا تسجيل معرّف الموارد المنتظم (URI) لإعادة التوجيه في OAuth الذي توفّره Firebase في وحدة تحكّم المطوّر الخاصة بموفّر الخدمة. يمكنك الاطّلاع على مستندات OIDC في Firebase للحصول على تعليمات تفصيلية حول الإعداد.
import FirebaseAuthSwiftUI
import FirebaseOAuthSwiftUI
import SwiftUI
struct ContentView: View {
let authService: AuthService
init() {
let configuration = AuthConfiguration()
authService = AuthService(configuration: configuration)
.withOAuthSignIn(
OAuthProviderSwift(
providerId: "oidc.line", // LINE OIDC provider
scopes: ["profile", "openid", "email"], // LINE requires these scopes
displayName: "Sign in with LINE",
buttonIcon: Image("line-logo"),
buttonBackgroundColor: .green,
buttonForegroundColor: .white
)
)
.withOAuthSignIn(
OAuthProviderSwift(
providerId: "oidc.custom-provider",
scopes: ["profile", "openid"],
displayName: "Sign in with Custom",
buttonIcon: Image(systemName: "person.circle"),
buttonBackgroundColor: .purple,
buttonForegroundColor: .white
)
)
}
var body: some View {
AuthPickerView {
Text("App Content")
}
.environment(authService)
}
}