Bạn có thể cho phép người dùng của mình xác thực với Firebase bằng tài khoản Facebook của họ bằng cách tích hợp Đăng nhập Facebook hoặc Đăng nhập có giới hạn Facebook vào ứng dụng của bạn.
Trước khi bắt đầu
Sử dụng Trình quản lý gói Swift để cài đặt và quản lý các phần phụ thuộc của Firebase.
- Trong Xcode, khi dự án ứng dụng của bạn đang mở, hãy điều hướng đến Tệp> Thêm gói .
- Khi được nhắc, hãy thêm kho lưu trữ SDK nền tảng Apple Firebase:
- Chọn thư viện Xác thực Firebase.
- Khi hoàn tất, Xcode sẽ tự động bắt đầu giải quyết và tải xuống các phần phụ thuộc của bạn trong nền.
https://github.com/firebase/firebase-ios-sdk
Tiếp theo, thực hiện một số bước cấu hình:
- Trên trang Facebook dành cho nhà phát triển , nhận ID ứng dụng và Bí mật ứng dụng cho ứng dụng của bạn.
- Kích hoạt Đăng nhập Facebook:
- Trong bảng điều khiển Firebase , hãy mở phần Xác thực.
- Trên tab Phương thức đăng nhập, hãy bật phương thức đăng nhập Facebook và chỉ định ID ứng dụng và Bí mật ứng dụng bạn nhận được từ Facebook.
- Sau đó, đảm bảo URI chuyển hướng OAuth của bạn (ví dụ:
my-app-12345.firebaseapp.com/__/auth/handler
) được liệt kê là một trong các URI chuyển hướng OAuth của bạn trong trang cài đặt ứng dụng Facebook của bạn trên trang Facebook dành cho nhà phát triển trong Sản phẩm Cài đặt> Cấu hình đăng nhập Facebook .
Thực hiện Đăng nhập Facebook
Để sử dụng Đăng nhập Facebook "cổ điển", hãy hoàn thành các bước sau. Ngoài ra, bạn có thể sử dụng Đăng nhập có giới hạn của Facebook, như được hiển thị trong phần tiếp theo.
- Tích hợp Đăng nhập Facebook vào ứng dụng của bạn bằng cách làm theo tài liệu của nhà phát triển . Khi bạn khởi tạo đối tượng
FBSDKLoginButton
, hãy đặt một đại biểu để nhận các sự kiện đăng nhập và đăng xuất. Ví dụ:Trong ủy quyền của bạn, hãy triển khaiNhanh
let loginButton = FBSDKLoginButton() loginButton.delegate = self
Objective-C
FBSDKLoginButton *loginButton = [[FBSDKLoginButton alloc] init]; loginButton.delegate = self;
didCompleteWithResult:error:
Nhanh
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); } }
- Nhập mô-đun
FirebaseCore
vàoUIApplicationDelegate
của bạn, cũng như bất kỳ mô-đun Firebase nào khác mà đại biểu ứng dụng của bạn sử dụng. Ví dụ: để sử dụng Cloud Firestore và Authentication:Nhanh
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Objective-C
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- Định cấu hình phiên bản được chia sẻ
FirebaseApp
, thường trong trình khởi tạoApp
của bạn hoặc ứng dụng của đại biểuapplication(_:didFinishLaunchingWithOptions:)
phương thức:Nhanh
// Use Firebase library to configure APIs FirebaseApp.configure()
Objective-C
// Use Firebase library to configure APIs [FIRApp configure];
- Sau khi người dùng đăng nhập thành công, trong quá trình triển khai
didCompleteWithResult:error:
hãy lấy mã thông báo truy cập cho người dùng đã đăng nhập và trao đổi nó để lấy thông tin đăng nhập Firebase:Nhanh
let credential = FacebookAuthProvider .credential(withAccessToken: AccessToken.current!.tokenString)
Objective-C
FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
Triển khai đăng nhập giới hạn Facebook
Để sử dụng Đăng nhập có giới hạn Facebook thay vì Đăng nhập Facebook "cổ điển", hãy hoàn thành các bước sau.
- Tích hợp Đăng nhập có giới hạn Facebook vào ứng dụng của bạn bằng cách làm theo tài liệu của nhà phát triển .
- Đối với mỗi yêu cầu đăng nhập, hãy tạo một chuỗi ngẫu nhiên duy nhất — "nonce" —mà bạn sẽ sử dụng để đảm bảo mã thông báo ID bạn nhận được đã được cấp cụ thể để đáp ứng yêu cầu xác thực của ứng dụng của bạn. Bước này rất quan trọng để ngăn chặn các cuộc tấn công phát lại. Bạn có thể tạo một nonce mật mã an toàn với
SecRandomCopyBytes(_:_:_)
, như trong ví dụ sau:Bạn sẽ gửi hàm băm SHA-256 của nonce cùng với yêu cầu đăng nhập của mình, mà Facebook sẽ chuyển không thay đổi trong phản hồi. Firebase xác thực phản hồi bằng cách băm nonce ban đầu và so sánh nó với giá trị mà Facebook đã chuyển.Nhanh
// Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce private func randomNonceString(length: Int = 32) -> String { precondition(length > 0) let charset: [Character] = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") var result = "" var remainingLength = length while remainingLength > 0 { let randoms: [UInt8] = (0 ..< 16).map { _ in var random: UInt8 = 0 let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random) if errorCode != errSecSuccess { fatalError( "Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)" ) } return random } randoms.forEach { random in if remainingLength == 0 { return } if random < charset.count { result.append(charset[Int(random)]) remainingLength -= 1 } } } return result }
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]; }
Nhanh
@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; }
- Khi bạn thiết lập
FBSDKLoginButton
, hãy đặt một đại biểu để nhận các sự kiện đăng nhập và đăng xuất, đặt chế độ theo dõi thànhFBSDKLoginTrackingLimited
và đính kèm một nonce. Ví dụ:Trong ủy quyền của bạn, hãy triển khaiNhanh
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:
Nhanh
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); } }
- Nhập mô-đun
FirebaseCore
vàoUIApplicationDelegate
của bạn, cũng như bất kỳ mô-đun Firebase nào khác mà đại biểu ứng dụng của bạn sử dụng. Ví dụ: để sử dụng Cloud Firestore và Authentication:Nhanh
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Objective-C
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- Định cấu hình phiên bản được chia sẻ
FirebaseApp
, thường trong trình khởi tạoApp
của bạn hoặc ứng dụng của đại biểuapplication(_:didFinishLaunchingWithOptions:)
phương thức:Nhanh
// Use Firebase library to configure APIs FirebaseApp.configure()
Objective-C
// Use Firebase library to configure APIs [FIRApp configure];
- Sau khi người dùng đăng nhập thành công, trong quá trình triển khai
didCompleteWithResult:error:
hãy sử dụng mã thông báo ID từ phản hồi của Facebook với nonce chưa băm để nhận thông tin đăng nhập Firebase:Nhanh
// 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];
Xác thực bằng Firebase
Cuối cùng, xác thực với Firebase bằng thông tin đăng nhập Firebase:
Nhanh
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; // ... }];
Bước tiếp theo
Sau khi người dùng đăng nhập lần đầu tiên, một tài khoản người dùng mới sẽ được tạo và liên kết với thông tin đăng nhập — nghĩa là tên người dùng và mật khẩu, số điện thoại hoặc thông tin nhà cung cấp xác thực — người dùng đã đăng nhập bằng. Tài khoản mới này được lưu trữ như một phần của dự án Firebase của bạn và có thể được sử dụng để xác định người dùng trên mọi ứng dụng trong dự án của bạn, bất kể người dùng đăng nhập bằng cách nào.
Trong ứng dụng của mình, bạn có thể lấy thông tin hồ sơ cơ bản của người dùng từ đối tượng
FIRUser
. Xem Quản lý người dùng .Trong Cơ sở dữ liệu thời gian thực Firebase và Quy tắc bảo mật lưu trữ đám mây, bạn có thể lấy ID người dùng duy nhất của người dùng đã đăng nhập từ biến
auth
và sử dụng nó để kiểm soát dữ liệu nào mà người dùng có thể truy cập.
Bạn có thể cho phép người dùng đăng nhập vào ứng dụng của mình bằng nhiều nhà cung cấp dịch vụ xác thực bằng cách liên kết thông tin xác thực của nhà cung cấp dịch vụ xác thực với tài khoản người dùng hiện có.
Để đăng xuất một người dùng, hãy gọi signOut:
Nhanh
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; }
Bạn cũng có thể muốn thêm mã xử lý lỗi cho đầy đủ các lỗi xác thực. Xem Xử lý lỗi .