شما میتوانید با ادغام ورود فیسبوک یا ورود محدود فیسبوک در برنامه خود، به کاربران خود اجازه دهید تا با استفاده از حسابهای فیسبوک خود در فایربیس احراز هویت کنند.
قبل از اینکه شروع کنی
برای نصب و مدیریت وابستگیهای Firebase از Swift Package Manager استفاده کنید.
- در Xcode، با باز کردن پروژه برنامه خود، به File > Add Packages بروید.
- وقتی از شما خواسته شد، مخزن SDK پلتفرمهای اپل فایربیس را اضافه کنید:
- کتابخانه Firebase Authentication را انتخاب کنید.
- پرچم
-ObjCرا به بخش Other Linker Flags در تنظیمات ساخت هدف خود اضافه کنید. - پس از اتمام، Xcode به طور خودکار شروع به حل و دانلود وابستگیهای شما در پسزمینه میکند.
https://github.com/firebase/firebase-ios-sdk.git
در مرحله بعد، برخی از مراحل پیکربندی را انجام دهید:
- در سایت فیسبوک برای توسعهدهندگان ، شناسه برنامه (App ID) و راز برنامه (App Secret) را برای برنامه خود دریافت کنید.
- فعال کردن ورود به فیسبوک:
- در کنسول Firebase ، بخش Authentication (احراز هویت) را باز کنید.
- در تب روش ورود ، روش ورود به سیستم فیسبوک را فعال کنید و شناسه برنامه (App ID) و راز برنامه (App Secret) که از فیسبوک دریافت کردهاید را مشخص کنید.
- سپس، مطمئن شوید که آدرس اینترنتی تغییر مسیر OAuth شما (مثلاً
my-app-12345.firebaseapp.com/__/auth/handler) به عنوان یکی از آدرسهای اینترنتی تغییر مسیر OAuth شما در صفحه تنظیمات برنامه فیسبوک شما در سایت فیسبوک برای توسعهدهندگان، در تنظیمات محصول > پیکربندی ورود به سیستم فیسبوک ، فهرست شده است.
ورود به سیستم فیسبوک را پیادهسازی کنید
برای استفاده از ورود به سیستم "کلاسیک" فیسبوک، مراحل زیر را انجام دهید. به عنوان یک جایگزین، میتوانید از ورود محدود فیسبوک، همانطور که در بخش بعدی نشان داده شده است، استفاده کنید.
- با دنبال کردن مستندات توسعهدهنده ، ورود به سیستم فیسبوک را در برنامه خود ادغام کنید. هنگام مقداردهی اولیه شیء
FBSDKLoginButton، یک نماینده برای دریافت رویدادهای ورود و خروج تنظیم کنید. برای مثال:در نماینده خود،سویفت
let loginButton = FBSDKLoginButton() loginButton.delegate = self
هدف-سی
FBSDKLoginButton *loginButton = [[FBSDKLoginButton alloc] init]; loginButton.delegate = self;
didCompleteWithResult:error:را پیادهسازی کنید.سویفت
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { if let error = error { print(error.localizedDescription) return } // ... }
هدف-سی
- (void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error { if (error == nil) { // ... } else { NSLog(error.localizedDescription); } }
- ماژول
FirebaseCoreرا درUIApplicationDelegateخود وارد کنید، و همچنین هر ماژول Firebase دیگری که app delegate شما از آن استفاده میکند. به عنوان مثال، برای استفاده از Cloud Firestore و Authentication :سویفتیوآی
import SwiftUI import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
سویفت
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
هدف-سی
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- یک نمونه اشتراکی
FirebaseAppدرapplication(_:didFinishLaunchingWithOptions:)از نماینده برنامه خود پیکربندی کنید:سویفتیوآی
// Use Firebase library to configure APIs FirebaseApp.configure()
سویفت
// Use Firebase library to configure APIs FirebaseApp.configure()
هدف-سی
// Use Firebase library to configure APIs [FIRApp configure];
- اگر از SwiftUI استفاده میکنید، باید یک نماینده برنامه ایجاد کنید و آن را از طریق
UIApplicationDelegateAdaptorیاNSApplicationDelegateAdaptorبه ساختارAppخود پیوست کنید. همچنین باید swizzling نماینده برنامه را غیرفعال کنید. برای اطلاعات بیشتر، به دستورالعملهای SwiftUI مراجعه کنید.سویفتیوآی
@main struct YourApp: App { // register app delegate for Firebase setup @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate var body: some Scene { WindowGroup { NavigationView { ContentView() } } } }
- پس از ورود موفقیتآمیز کاربر، در پیادهسازی
didCompleteWithResult:error:یک توکن دسترسی برای کاربر وارد شده دریافت کرده و آن را با یک اعتبارنامه Firebase مبادله کنید:سویفت
let credential = FacebookAuthProvider .credential(withAccessToken: AccessToken.current!.tokenString)
هدف-سی
FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
ورود محدود فیسبوک را پیادهسازی کنید
برای استفاده از ورود محدود فیسبوک به جای ورود «کلاسیک» فیسبوک، مراحل زیر را انجام دهید.
- با دنبال کردن مستندات توسعهدهنده، ورود محدود فیسبوک را در برنامه خود ادغام کنید.
- برای هر درخواست ورود، یک رشته تصادفی منحصر به فرد - یک "nonce" - ایجاد کنید که از آن برای اطمینان از اعطای توکن شناسه به طور خاص در پاسخ به درخواست احراز هویت برنامه خود استفاده خواهید کرد. این مرحله برای جلوگیری از حملات بازپخش مهم است. میتوانید با استفاده از
SecRandomCopyBytes(_:_:_)، مانند مثال زیر، یک nonce امن رمزنگاری شده ایجاد کنید:شما هش SHA-256 مربوط به nonce را به همراه درخواست ورود خود ارسال خواهید کرد که فیسبوک آن را بدون تغییر در پاسخ ارسال خواهد کرد. فایربیس با هش کردن nonce اصلی و مقایسه آن با مقداری که فیسبوک ارسال کرده است، پاسخ را تأیید میکند.سویفت
private func randomNonceString(length: Int = 32) -> String { precondition(length > 0) var randomBytes = [UInt8](repeating: 0, count: length) let errorCode = SecRandomCopyBytes(kSecRandomDefault, randomBytes.count, &randomBytes) if errorCode != errSecSuccess { fatalError( "Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)" ) } let charset: [Character] = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") let nonce = randomBytes.map { byte in // Pick a random character from the set, wrapping around if needed. charset[Int(byte) % charset.count] } return String(nonce) }
هدف-سی
// Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce - (NSString *)randomNonce:(NSInteger)length { NSAssert(length > 0, @"Expected nonce to have positive length"); NSString *characterSet = @"0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._"; NSMutableString *result = [NSMutableString string]; NSInteger remainingLength = length; while (remainingLength > 0) { NSMutableArray *randoms = [NSMutableArray arrayWithCapacity:16]; for (NSInteger i = 0; i < 16; i++) { uint8_t random = 0; int errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random); NSAssert(errorCode == errSecSuccess, @"Unable to generate nonce: OSStatus %i", errorCode); [randoms addObject:@(random)]; } for (NSNumber *random in randoms) { if (remainingLength == 0) { break; } if (random.unsignedIntValue < characterSet.length) { unichar character = [characterSet characterAtIndex:random.unsignedIntValue]; [result appendFormat:@"%C", character]; remainingLength--; } } } return [result copy]; }
سویفت
@available(iOS 13, *) private func sha256(_ input: String) -> String { let inputData = Data(input.utf8) let hashedData = SHA256.hash(data: inputData) let hashString = hashedData.compactMap { String(format: "%02x", $0) }.joined() return hashString }
هدف-سی
- (NSString *)stringBySha256HashingString:(NSString *)input { const char *string = [input UTF8String]; unsigned char result[CC_SHA256_DIGEST_LENGTH]; CC_SHA256(string, (CC_LONG)strlen(string), result); NSMutableString *hashed = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) { [hashed appendFormat:@"%02x", result[i]]; } return hashed; }
- هنگام تنظیم
FBSDKLoginButton، یک نماینده برای دریافت رویدادهای ورود و خروج تنظیم کنید، حالت ردیابی را رویFBSDKLoginTrackingLimitedتنظیم کنید و یک nonce پیوست کنید. برای مثال:در نماینده خود،سویفت
func setupLoginButton() { let nonce = randomNonceString() currentNonce = nonce loginButton.delegate = self loginButton.loginTracking = .limited loginButton.nonce = sha256(nonce) }
هدف-سی
- (void)setupLoginButton { NSString *nonce = [self randomNonce:32]; self.currentNonce = nonce; self.loginButton.delegate = self; self.loginButton.loginTracking = FBSDKLoginTrackingLimited self.loginButton.nonce = [self stringBySha256HashingString:nonce]; }
didCompleteWithResult:error:را پیادهسازی کنید.سویفت
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { if let error = error { print(error.localizedDescription) return } // ... }
هدف-سی
- (void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error { if (error == nil) { // ... } else { NSLog(error.localizedDescription); } }
- ماژول
FirebaseCoreرا درUIApplicationDelegateخود وارد کنید، و همچنین هر ماژول Firebase دیگری که app delegate شما از آن استفاده میکند. به عنوان مثال، برای استفاده از Cloud Firestore و Authentication :سویفتیوآی
import SwiftUI import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
سویفت
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
هدف-سی
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- یک نمونه اشتراکی
FirebaseAppدرapplication(_:didFinishLaunchingWithOptions:)از نماینده برنامه خود پیکربندی کنید:سویفتیوآی
// Use Firebase library to configure APIs FirebaseApp.configure()
سویفت
// Use Firebase library to configure APIs FirebaseApp.configure()
هدف-سی
// Use Firebase library to configure APIs [FIRApp configure];
- اگر از SwiftUI استفاده میکنید، باید یک نماینده برنامه ایجاد کنید و آن را از طریق
UIApplicationDelegateAdaptorیاNSApplicationDelegateAdaptorبه ساختارAppخود پیوست کنید. همچنین باید swizzling نماینده برنامه را غیرفعال کنید. برای اطلاعات بیشتر، به دستورالعملهای SwiftUI مراجعه کنید.سویفتیوآی
@main struct YourApp: App { // register app delegate for Firebase setup @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate var body: some Scene { WindowGroup { NavigationView { ContentView() } } } }
- پس از اینکه کاربر با موفقیت وارد سیستم شد، در پیادهسازی
didCompleteWithResult:error:خود، از توکن ID از پاسخ فیسبوک به همراه nonce هش نشده برای دریافت اعتبارنامه Firebase استفاده کنید:سویفت
// Initialize a Firebase credential. let idTokenString = AuthenticationToken.current?.tokenString let nonce = currentNonce let credential = OAuthProvider.credential(withProviderID: "facebook.com", idToken: idTokenString!, rawNonce: nonce)
هدف-سی
// Initialize a Firebase credential. NSString *idTokenString = FBSDKAuthenticationToken.currentAuthenticationToken.tokenString; NSString *rawNonce = self.currentNonce; FIROAuthCredential *credential = [FIROAuthProvider credentialWithProviderID:@"facebook.com" IDToken:idTokenString rawNonce:rawNonce];
احراز هویت با فایربیس
در نهایت، با استفاده از اعتبارنامه Firebase، با Firebase احراز هویت کنید:
سویفت
Auth.auth().signIn(with: credential) { authResult, error in if let error = error { let authError = error as NSError if isMFAEnabled, authError.code == AuthErrorCode.secondFactorRequired.rawValue { // The user is a multi-factor user. Second factor challenge is required. let resolver = authError .userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver var displayNameString = "" for tmpFactorInfo in resolver.hints { displayNameString += tmpFactorInfo.displayName ?? "" displayNameString += " " } self.showTextInputPrompt( withMessage: "Select factor to sign in\n\(displayNameString)", completionBlock: { userPressedOK, displayName in var selectedHint: PhoneMultiFactorInfo? for tmpFactorInfo in resolver.hints { if displayName == tmpFactorInfo.displayName { selectedHint = tmpFactorInfo as? PhoneMultiFactorInfo } } PhoneAuthProvider.provider() .verifyPhoneNumber(with: selectedHint!, uiDelegate: nil, multiFactorSession: resolver .session) { verificationID, error in if error != nil { print( "Multi factor start sign in failed. Error: \(error.debugDescription)" ) } else { self.showTextInputPrompt( withMessage: "Verification code for \(selectedHint?.displayName ?? "")", completionBlock: { userPressedOK, verificationCode in let credential: PhoneAuthCredential? = PhoneAuthProvider.provider() .credential(withVerificationID: verificationID!, verificationCode: verificationCode!) let assertion: MultiFactorAssertion? = PhoneMultiFactorGenerator .assertion(with: credential!) resolver.resolveSignIn(with: assertion!) { authResult, error in if error != nil { print( "Multi factor finanlize sign in failed. Error: \(error.debugDescription)" ) } else { self.navigationController?.popViewController(animated: true) } } } ) } } } ) } else { self.showMessagePrompt(error.localizedDescription) return } // ... return } // User is signed in // ... }
هدف-سی
[[FIRAuth auth] signInWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (isMFAEnabled && error && error.code == FIRAuthErrorCodeSecondFactorRequired) { FIRMultiFactorResolver *resolver = error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey]; NSMutableString *displayNameString = [NSMutableString string]; for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) { [displayNameString appendString:tmpFactorInfo.displayName]; [displayNameString appendString:@" "]; } [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Select factor to sign in\n%@", displayNameString] completionBlock:^(BOOL userPressedOK, NSString *_Nullable displayName) { FIRPhoneMultiFactorInfo* selectedHint; for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) { if ([displayName isEqualToString:tmpFactorInfo.displayName]) { selectedHint = (FIRPhoneMultiFactorInfo *)tmpFactorInfo; } } [FIRPhoneAuthProvider.provider verifyPhoneNumberWithMultiFactorInfo:selectedHint UIDelegate:nil multiFactorSession:resolver.session completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { if (error) { [self showMessagePrompt:error.localizedDescription]; } else { [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Verification code for %@", selectedHint.displayName] completionBlock:^(BOOL userPressedOK, NSString *_Nullable verificationCode) { FIRPhoneAuthCredential *credential = [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID verificationCode:verificationCode]; FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential]; [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error) { [self showMessagePrompt:error.localizedDescription]; } else { NSLog(@"Multi factor finanlize sign in succeeded."); } }]; }]; } }]; }]; } else if (error) { // ... return; } // User successfully signed in. Get user data from the FIRUser object if (authResult == nil) { return; } FIRUser *user = authResult.user; // ... }];
مراحل بعدی
پس از اینکه کاربر برای اولین بار وارد سیستم میشود، یک حساب کاربری جدید ایجاد میشود و به اطلاعات احراز هویت - یعنی نام کاربری و رمز عبور، شماره تلفن یا اطلاعات ارائه دهنده مجوز - که کاربر با آن وارد سیستم شده است، پیوند داده میشود. این حساب جدید به عنوان بخشی از پروژه Firebase شما ذخیره میشود و میتواند برای شناسایی کاربر در هر برنامه در پروژه شما، صرف نظر از نحوه ورود کاربر، مورد استفاده قرار گیرد.
در برنامههای خود، میتوانید اطلاعات اولیه پروفایل کاربر را از شیء
Userدریافت کنید. به بخش مدیریت کاربران مراجعه کنید.در قوانین امنیتی پایگاه داده و Cloud Storage Firebase Realtime Database ، میتوانید شناسه کاربری منحصر به فرد کاربر وارد شده را از متغیر
authدریافت کنید و از آن برای کنترل دادههایی که کاربر میتواند به آنها دسترسی داشته باشد، استفاده کنید.
برای خروج از سیستم کاربر، تابع signOut: را فراخوانی کنید.
سویفت
let firebaseAuth = Auth.auth() do { try firebaseAuth.signOut() } catch let signOutError as NSError { print("Error signing out: %@", signOutError) }
هدف-سی
NSError *signOutError; BOOL status = [[FIRAuth auth] signOut:&signOutError]; if (!status) { NSLog(@"Error signing out: %@", signOutError); return; }
همچنین میتوانید کد مدیریت خطا را برای طیف کامل خطاهای احراز هویت اضافه کنید. به بخش مدیریت خطاها مراجعه کنید.