Bạn có thể cho phép người dùng của mình xác thực với Firebase bằng ID Apple của họ bằng cách sử dụng SDK Firebase để thực hiện quy trình đăng nhập OAuth 2.0 từ đầu đến cuối.
Trước khi bắt đầu
Để đăng nhập người dùng bằng Apple, trước tiên hãy định cấu hình Đăng nhập với Apple trên trang web dành cho nhà phát triển của Apple, sau đó bật Apple làm nhà cung cấp dịch vụ đăng nhập cho dự án Firebase của bạn.
Tham gia chương trình nhà phát triển Apple
Đăng nhập với Apple chỉ có thể được định cấu hình bởi các thành viên của Chương trình nhà phát triển Apple .
Định cấu hình Đăng nhập với Apple
Đăng nhập Apple phải được bật và định cấu hình đúng cách trong dự án Firebase của bạn. Cấu hình khác nhau giữa các nền tảng Android và Apple. Vui lòng làm theo phần "Định cấu hình Đăng nhập bằng Apple" của các nền tảng Apple và / hoặc hướng dẫn Android trước khi tiếp tục.Cho phép Apple làm nhà cung cấp dịch vụ đăng nhập
- 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 nhà cung cấp Apple .
- Định cấu hình cài đặt nhà cung cấp Đăng nhập Apple:
- Nếu bạn chỉ triển khai ứng dụng của mình trên các nền tảng của Apple, bạn có thể để trống các trường ID dịch vụ, ID nhóm Apple, khóa cá nhân và ID khóa.
- Để được hỗ trợ trên các thiết bị Android:
- Thêm Firebase vào dự án Android của bạn . Đảm bảo đăng ký chữ ký SHA-1 của ứng dụng khi bạn thiết lập ứng dụng của mình trong bảng điều khiển Firebase.
- 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 nhà cung cấp Apple . Chỉ định ID dịch vụ bạn đã tạo trong phần trước. Ngoài ra, trong phần cấu hình luồng mã OAuth, hãy chỉ định ID nhóm Apple của bạn và khóa cá nhân và ID khóa mà bạn đã tạo trong phần trước.
Tuân thủ các yêu cầu về dữ liệu ẩn danh của Apple
Đăng nhập bằng Apple cung cấp cho người dùng tùy chọn ẩn danh dữ liệu của họ, bao gồm địa chỉ email, khi đăng nhập. Người dùng chọn tùy chọn này có địa chỉ email với miền privaterelay.appleid.com
. Khi bạn sử dụng Đăng nhập bằng Apple trong ứng dụng của mình, bạn phải tuân thủ mọi điều khoản hoặc chính sách nhà phát triển hiện hành từ Apple về các ID Apple ẩn danh này.
Điều này bao gồm việc nhận được bất kỳ sự đồng ý cần thiết nào của người dùng trước khi bạn liên kết bất kỳ thông tin cá nhân nhận dạng trực tiếp nào với ID Apple ẩn danh. Khi sử dụng Xác thực Firebase, điều này có thể bao gồm các hành động sau:
- Liên kết địa chỉ email với ID Apple ẩn danh hoặc ngược lại.
- Liên kết số điện thoại với ID Apple ẩn danh hoặc ngược lại
- Liên kết thông tin đăng nhập xã hội không ẩn danh (Facebook, Google, v.v.) với ID Apple ẩn danh hoặc ngược lại.
Danh sách trên không toàn diện. Tham khảo Thỏa thuận cấp phép chương trình nhà phát triển của Apple trong phần Tư cách thành viên của tài khoản nhà phát triển của bạn để đảm bảo ứng dụng của bạn đáp ứng các yêu cầu của Apple.
Truy cập lớp firebase::auth::Auth
Lớp Auth
là cổng cho tất cả các lệnh gọi API.- Thêm tệp tiêu đề Ứng dụng và Xác thực:
#include "firebase/app.h" #include "firebase/auth.h"
- Trong mã khởi tạo của bạn, hãy tạo một lớp
firebase::App
.#if defined(__ANDROID__) firebase::App* app = firebase::App::Create(firebase::AppOptions(), my_jni_env, my_activity); #else firebase::App* app = firebase::App::Create(firebase::AppOptions()); #endif // defined(__ANDROID__)
- Có được lớp
firebase::auth::Auth
chofirebase::App
của bạn. Có một ánh xạ 1-1 giữaApp
vàAuth
thực.firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);
Xử lý quy trình đăng nhập với SDK Firebase
Quy trình Đăng nhập với Apple khác nhau trên các nền tảng Apple và Android.
Trên các nền tảng của Apple
Xác thực người dùng của bạn với Firebase thông qua SDK mục tiêu-C đăng nhập của Apple được gọi từ mã C ++ của bạ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 — "nonce" —mà bạn sẽ sử dụng để đảm bảo mã thông báo ID mà 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.
- (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--; } } } }
Bạn sẽ gửi hàm băm SHA256 của nonce cùng với yêu cầu đăng nhập của mình, mà Apple 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à Apple đã chuyển.
Bắt đầu quy trình đăng nhập của Apple, bao gồm trong yêu cầu của bạn hàm băm SHA256 của nonce và lớp đại biểu sẽ xử lý phản hồi của Apple (xem bước tiếp theo):
- (void)startSignInWithAppleFlow { NSString *nonce = [self randomNonce:32]; self.currentNonce = nonce; ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init]; ASAuthorizationAppleIDRequest *request = [appleIDProvider createRequest]; request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail]; request.nonce = [self stringBySha256HashingString:nonce]; ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]]; authorizationController.delegate = self; authorizationController.presentationContextProvider = self; [authorizationController performRequests]; } - (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; }
Xử lý phản hồi của Apple khi bạn triển khai ASAuthorizationControllerDelegate`. Nếu đăng nhập thành công, hãy sử dụng mã thông báo ID từ phản hồi của Apple với nonce chưa băm để xác thực với Firebase:
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) { if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) { ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential; NSString *rawNonce = self.currentNonce; NSAssert(rawNonce != nil, @"Invalid state: A login callback was received, but no login request was sent."); if (appleIDCredential.identityToken == nil) { NSLog(@"Unable to fetch identity token."); return; } NSString *idToken = [[NSString alloc] initWithData:appleIDCredential.identityToken encoding:NSUTF8StringEncoding]; if (idToken == nil) { NSLog(@"Unable to serialize id token from data: %@", appleIDCredential.identityToken); } }
Sử dụng chuỗi mã thông báo kết quả và mã thông báo gốc để tạo Thông tin xác thực Firebase và đăng nhập vào Firebase.
firebase::auth::OAuthProvider::GetCredential( /*provider_id=*/"apple.com", token, nonce, /*access_token=*/nullptr); firebase::Future<firebase::auth::User*> result = auth->SignInWithCredential(credential);
Mẫu tương tự có thể được sử dụng với
Reauthenticate
có thể được sử dụng để truy xuất thông tin đăng nhập mới cho các hoạt động nhạy cảm yêu cầu đăng nhập gần đây.firebase::Future<firebase::auth::SignInResult> result = user->Reauthenticate(credential);
Mẫu tương tự có thể được sử dụng để liên kết tài khoản với Đăng nhập Apple. Tuy nhiên, bạn có thể gặp lỗi khi tài khoản Firebase hiện tại đã được liên kết với tài khoản Apple mà bạn đang cố gắng liên kết. Khi điều này xảy ra, tương lai sẽ trả về trạng thái của
kAuthErrorCredentialAlreadyInUse
và đối tượng UserInfo củaSignInResult
có thể chứa cậpupdated_credential
hợp lệ. Thông tin đăng nhập này có thể được sử dụng để đăng nhập vào tài khoản được liên kết với Apple thông quaSignInWithCredential
mà không cần tạo mã thông báo Đăng nhập Apple khác và không phải vậy.Lưu ý rằng bạn phải sử dụng
LinkAndRetrieveDataWithCredential
cho thao tác này để chứa thông tin đăng nhập vìupdated_credential
là thành viên của đối tượngSignInResult.UserInfo
.firebase::Future<firebase::auth::SignInResult> link_result = auth->current_user()->LinkAndRetrieveDataWithCredential(credential); // To keep example simple, wait on the current thread until call completes. while (link_result.status() == firebase::kFutureStatusPending) { Wait(100); } // Determine the result of the link attempt if (link_result.error() == firebase::auth::kAuthErrorNone) { // user linked correctly. } else if (link_result.error() == firebase::auth::kAuthErrorCredentialAlreadyInUse && link_result.result()->info.updated_credential.is_valid()) { // Sign In with the new credential firebase::Future<firebase::auth::User*> result = auth->SignInWithCredential( link_result.result()->info.updated_credential); } else { // Another link error occurred. }
Trên Android
Trên Android, xác thực người dùng của bạn với Firebase bằng cách tích hợp Đăng nhập OAuth chung dựa trên web vào ứng dụng của bạn bằng cách sử dụng SDK Firebase để thực hiện quy trình đăng nhập từ đầu đến cuối.
Để xử lý quy trình đăng nhập với SDK Firebase, hãy làm theo các bước sau:
Tạo một phiên bản của
FederatedOAuthProviderData
được định cấu hình với ID nhà cung cấp phù hợp với Apple.firebase::auth::FederatedOAuthProviderData provider_data("apple.com");
Tùy chọn: Chỉ định phạm vi OAuth 2.0 bổ sung ngoài phạm vi mặc định mà bạn muốn yêu cầu từ nhà cung cấp xác thực.
provider_data.scopes.push_back("email"); provider_data.scopes.push_back("name");
Tùy chọn: Nếu bạn muốn hiển thị màn hình đăng nhập của Apple bằng ngôn ngữ không phải tiếng Anh, hãy đặt tham số
locale
. Xem Đăng nhập bằng tài liệu Apple để biết các ngôn ngữ được hỗ trợ.// Localize to French. provider_data.custom_parameters["language"] = "fr"; ```
Khi dữ liệu nhà cung cấp của bạn đã được định cấu hình, hãy sử dụng nó để tạo FederatedOAuthProvider.
// Construct a FederatedOAuthProvider for use in Auth methods. firebase::auth::FederatedOAuthProvider provider(provider_data);
Xác thực với Firebase bằng đối tượng nhà cung cấp Auth. Lưu ý rằng không giống như các hoạt động FirebaseAuth khác, thao tác này sẽ kiểm soát giao diện người dùng của bạn bằng cách bật lên một chế độ xem web trong đó người dùng có thể nhập thông tin đăng nhập của họ.
Để bắt đầu quy trình đăng nhập, hãy gọi
signInWithProvider
:firebase::Future<firebase::auth::SignInResult> result = auth->SignInWithProvider(provider_data);
Sau đó, ứng dụng của bạn có thể đợi hoặc đăng ký một cuộc gọi lại trong Tương lai .
Mẫu tương tự có thể được sử dụng với
ReauthenticateWithProvider
có thể được sử dụng để truy xuất thông tin đăng nhập mới cho các hoạt động nhạy cảm yêu cầu đăng nhập gần đây.firebase::Future<firebase::auth::SignInResult> result = user->ReauthenticateWithProvider(provider_data);
Sau đó, ứng dụng của bạn có thể đợi hoặc đăng ký một cuộc gọi lại trong Tương lai .
Và, bạn có thể sử dụng
linkWithCredential()
để liên kết các nhà cung cấp danh tính khác nhau với các tài khoản hiện có.Lưu ý rằng Apple yêu cầu bạn phải có sự đồng ý rõ ràng từ người dùng trước khi bạn liên kết tài khoản Apple của họ với dữ liệu khác.
Ví dụ: để liên kết tài khoản Facebook với tài khoản Firebase hiện tại, hãy sử dụng mã thông báo truy cập bạn nhận được khi đăng nhập người dùng vào Facebook:
// Initialize a Facebook credential with a Facebook access token. AuthCredential credential = firebase::auth::FacebookAuthProvider.getCredential(token); // Assuming the current user is an Apple user linking a Facebook provider. firebase::Future<firebase::auth::SignInResult> result = auth.getCurrentUser().linkWithCredential(credential);
Đăng nhập bằng Apple Notes
Không giống như các nhà cung cấp khác được hỗ trợ bởi Firebase Auth, Apple không cung cấp URL ảnh.
Ngoài ra, khi người dùng chọn không chia sẻ email của họ với ứng dụng, Apple cung cấp một địa chỉ email duy nhất cho người dùng đó (có dạng xyz@privaterelay.appleid.com
), địa chỉ này chia sẻ với ứng dụng của bạn. Nếu bạn đã định cấu hình dịch vụ chuyển tiếp email riêng tư, Apple sẽ chuyển tiếp các email được gửi đến địa chỉ ẩn danh đến địa chỉ email thực của người dùng.
Apple chỉ chia sẻ thông tin người dùng, chẳng hạn như tên hiển thị với các ứng dụng vào lần đầu tiên người dùng đăng nhập. Thông thường, Firebase lưu trữ tên hiển thị vào lần đầu tiên người dùng đăng nhập với Apple, bạn có thể lấy thông tin này bằng getCurrentUser().getDisplayName()
. Tuy nhiên, nếu trước đây bạn đã sử dụng Apple để đăng nhập người dùng vào ứng dụng mà không sử dụng Firebase, thì Apple sẽ không cung cấp cho Firebase tên hiển thị của người dùng.
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 như thế 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 firebase :: auth :: user. 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.