با ادغام «ورود به سیستم Facebook» یا «ورود به سیستم محدود Facebook» در برنامهتان، میتوانید به کاربران اجازه دهید بااستفاده از حسابهای Facebook خود با Firebase اصالتسنجی کنند.
قبل از شروع
از «مدیر بسته Swift» برای نصب و مدیریت وابستگیهای Firebase استفاده کنید.
- در Xcode، با باز بودن پروژه برنامه، به File > Add Packages (فایل > افزودن بستهها) پیمایش کنید.
- وقتی درخواست شد، مخزن کیت توسعه نرمافزار پلاتفرمهای Firebase Apple را اضافه کنید:
- کتابخانه Firebase Authentication را انتخاب کنید.
- پرچم
-ObjCرا به بخش پرچمهای پیونددهنده دیگر در تنظیمات ساخت هدف اضافه کنید. - پساز اتمام، Xcode بهطور خودکار شروع به حل و بارگیری وابستگیهای شما در پسزمینه میکند.
https://github.com/firebase/firebase-ios-sdk.git
سپس، چند مرحله پیکربندی را انجام دهید:
- در سایت Facebook for Developers، شناسه برنامه و رمز برنامه را برای برنامهتان دریافت کنید.
-
«ورود به سیستم با Facebook» را بهعنوان ارائهدهنده ورود به سیستم برای پروژه Firebase خود فعال کنید:
- در کنسول Firebase، به امنیت > اصالتسنجی بروید.
- در برگه روش ورود به سیستم، ارائهدهنده ورود به سیستم Facebook را فعال کنید و شناسه برنامه و رمز برنامه را که از Facebook دریافت کردهاید مشخص کنید.
-
مطمئن شوید که شناسه «URI هدایت OAuth» شما (برای مثال،
my-app-12345.firebaseapp.com/__/auth/handler) بهعنوان یکی از شناسههای «URI هدایت OAuth» در صفحه تنظیمات برنامه Facebook شما در سایت Facebook for Developers در پیکربندی تنظیمات محصول > ورود به سیستم Facebook فهرست شده باشد.
پیادهسازی «ورود به سیستم فیسبوک»
برای استفاده از «کلاسیک» ورود به سیستم Facebook، مراحل زیر را تکمیل کنید. یا میتوانید از «ورود به سیستم محدود Facebook» که در بخش بعدی نشان داده شده است استفاده کنید.
- با دنبال کردن
اسناد توسعهدهنده، «ورود به سیستم Facebook» را در برنامهتان ادغام کنید. وقتی شیء
FBSDKLoginButtonرا مقداردهی اولیه میکنید، نمایندهای را برای دریافت رویدادهای ورود به سیستم و خروج از سیستم تنظیم کنید. برای مثال:در نمایندهتان،Swift
let loginButton = FBSDKLoginButton() loginButton.delegate = self
Objective-C
FBSDKLoginButton *loginButton = [[FBSDKLoginButton alloc] init]; loginButton.delegate = self;
didCompleteWithResult:error:را پیادهسازی کنید.Swift
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { if let error = error { print(error.localizedDescription) return } // ... }
Objective-C
- (void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error { if (error == nil) { // ... } else { NSLog(error.localizedDescription); } }
- واحد
FirebaseCoreرا درUIApplicationDelegateو همچنین هر واحد Firebase دیگری که نماینده برنامه شما استفاده میکند وارد کنید. برای مثال، برای استفاده از Cloud Firestore و Authentication:SwiftUI
import SwiftUI import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Swift
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Objective-C
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- نمونه مشترکی را در
FirebaseAppروش نماینده برنامه خود پیکربندی کنید:application(_:didFinishLaunchingWithOptions:)SwiftUI
// Use Firebase library to configure APIs FirebaseApp.configure()
Swift
// Use Firebase library to configure APIs FirebaseApp.configure()
Objective-C
// Use Firebase library to configure APIs [FIRApp configure];
- اگر از SwiftUI استفاده میکنید، باید نماینده برنامه ایجاد کنید و آن را ازطریق
UIApplicationDelegateAdaptorیاNSApplicationDelegateAdaptorبه ساختارAppپیوست کنید. همچنین باید تغییرات در نماینده برنامه را غیرفعال کنید. برای اطلاعات بیشتر، دستورالعملهای SwiftUI را ببینید.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 مبادله کنید:Swift
let credential = FacebookAuthProvider .credential(withAccessToken: AccessToken.current!.tokenString)
Objective-C
FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
پیادهسازی ورود محدود به سیستم Facebook
برای استفاده از «ورود به سیستم محدود Facebook» بهجای «ورود به سیستم کلاسیک Facebook»، مراحل زیر را تکمیل کنید.
- با دنبال کردن اسناد توسعهدهنده، «ورود به سیستم محدود Facebook» را در برنامهتان ادغام کنید.
- برای هر درخواست ورود به سیستم، یک رشته تصادفی منحصربهفرد—یک «نانس»—تولید کنید که
از آن برای اطمینان از اینکه شناسه دریافتی شما بهطور خاص در
پاسخ به درخواست اصالتسنجی برنامه شما اعطا شده است استفاده خواهید کرد. این مرحله برای جلوگیری از حملات بازپخش مهم است.
میتوانید یک نانس رمزنگاریشده ایمن با
SecRandomCopyBytes(_:_:_)، مانند مثال زیر، تولید کنید:درخواست ورود به سیستم را با درهمسازی SHA-256 مقدار یکبارمصرف ارسال میکنید، که Facebook آن را بدون تغییر در پاسخ ارسال میکند. Firebase پاسخ را با درهمسازی مقدار یکبارمصرف اصلی و مقایسه آن با مقدار ارسالشده توسط Facebook اعتبارسنجی میکند.Swift
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) }
Objective-C
// 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]; }
Swift
@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 }
Objective-C
- (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تنظیم کنید، و یک نانس پیوست کنید. برای مثال:در نمایندهتان،Swift
func setupLoginButton() { let nonce = randomNonceString() currentNonce = nonce loginButton.delegate = self loginButton.loginTracking = .limited loginButton.nonce = sha256(nonce) }
Objective-C
- (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:را پیادهسازی کنید.Swift
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { if let error = error { print(error.localizedDescription) return } // ... }
Objective-C
- (void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error { if (error == nil) { // ... } else { NSLog(error.localizedDescription); } }
- واحد
FirebaseCoreرا درUIApplicationDelegateو همچنین هر واحد Firebase دیگری که نماینده برنامه شما استفاده میکند وارد کنید. برای مثال، برای استفاده از Cloud Firestore و Authentication:SwiftUI
import SwiftUI import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Swift
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Objective-C
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- نمونه مشترکی را در
FirebaseAppروش نماینده برنامه خود پیکربندی کنید:application(_:didFinishLaunchingWithOptions:)SwiftUI
// Use Firebase library to configure APIs FirebaseApp.configure()
Swift
// Use Firebase library to configure APIs FirebaseApp.configure()
Objective-C
// Use Firebase library to configure APIs [FIRApp configure];
- اگر از SwiftUI استفاده میکنید، باید نماینده برنامه ایجاد کنید و آن را ازطریق
UIApplicationDelegateAdaptorیاNSApplicationDelegateAdaptorبه ساختارAppپیوست کنید. همچنین باید تغییرات در نماینده برنامه را غیرفعال کنید. برای اطلاعات بیشتر، دستورالعملهای SwiftUI را ببینید.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:، از شناسه رمز از پاسخ Facebook با مقدار یکبارمصرف بدون درهمسازی برای دریافت اطلاعات اعتباری Firebase استفاده کنید:Swift
// Initialize a Firebase credential. let idTokenString = AuthenticationToken.current?.tokenString let nonce = currentNonce let credential = OAuthProvider.credential(withProviderID: "facebook.com", idToken: idTokenString!, rawNonce: nonce)
Objective-C
// 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 با Firebase اصالتسنجی کنید:
Swift
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 // ... }
Objective-C
[[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شیء دریافت کنید. به مدیریت کاربران مراجعه کنید. در Firebase Realtime Database و Cloud Storage قوانین امنیتی، میتوانید شناسه کاربر یکتای کاربر واردشده به سیستم را از متغیر
authدریافت کنید و از آن برای کنترل دادههایی که کاربر میتواند به آنها دسترسی داشته باشد استفاده کنید.
میتوانید به کاربران اجازه دهید با پیوند دادن اطلاعات اعتباری ارائهدهنده اصالتسنجی به حساب کاربری موجود بااستفاده از چندین ارائهدهنده اصالتسنجی به سیستم برنامهتان وارد شوند.
برای خارج کردن کاربر از سیستم،
signOut: را فراخوانی کنید.
Swift
let firebaseAuth = Auth.auth() do { try firebaseAuth.signOut() } catch let signOutError as NSError { print("Error signing out: %@", signOutError) }
Objective-C
NSError *signOutError; BOOL status = [[FIRAuth auth] signOut:&signOutError]; if (!status) { NSLog(@"Error signing out: %@", signOutError); return; }
همچنین ممکن است بخواهید کد مدیریت خطا را برای طیف کامل خطاهای اصالتسنجی اضافه کنید. مدیریت خطاها را ببینید.