אתם יכולים לאפשר למשתמשים שלכם לבצע אימות באמצעות Firebase באמצעות Apple ID שלהם, על ידי שימוש ב-Firebase SDK כדי לבצע את תהליך הכניסה מקצה לקצה של OAuth 2.0.
לפני שמתחילים
כדי לאפשר למשתמשים להיכנס באמצעות Apple, קודם צריך להגדיר את הכניסה באמצעות Apple באתר למפתחים של Apple, ואז להפעיל את Apple כספק כניסה בפרויקט Firebase.
הצטרפות לתוכנית המפתחים של אפל
אפשר להגדיר כניסה באמצעות Apple רק על ידי חברים בתוכנית המפתחים של Apple.
הגדרת כניסה באמצעות Apple
צריך להפעיל את התכונה 'כניסה באמצעות חשבון Apple' ולהגדיר אותה בצורה נכונה בפרויקט Firebase. ההגדרה משתנה בין פלטפורמות Android ו-Apple. לפני שממשיכים, צריך לפעול לפי ההוראות שבקטע 'הגדרת כניסה באמצעות Apple' במדריכים בנושא פלטפורמות של Apple או Android.הפעלת Apple כספק כניסה
- במסוף Firebase, פותחים את הקטע אימות. בכרטיסייה שיטת הכניסה, מפעילים את הספק Apple.
- מגדירים את הספק Apple Sign-in:
- אם אתם פורסים את האפליקציה רק בפלטפורמות של אפל, אתם יכולים להשאיר את השדות Service ID, Apple Team ID, private key ו-key ID ריקים.
- לקבלת תמיכה במכשירי Android:
- איך מוסיפים את Firebase לפרויקט Android חשוב לרשום את חתימת ה-SHA-1 של האפליקציה כשמגדירים את האפליקציה במסוף Firebase.
- במסוף Firebase, פותחים את הקטע אימות. בכרטיסייה שיטת הכניסה, מפעילים את הספק Apple. מציינים את מזהה השירות שיצרתם בקטע הקודם. בנוסף, בקטע ההגדרות של תהליך קבלת הרשאת OAuth, צריך לציין את מזהה הצוות שלכם ב-Apple, את המפתח הפרטי ואת מזהה המפתח שיצרתם בקטע הקודם.
עמידה בדרישות של Apple לגבי נתונים שעברו אנונימיזציה
התכונה 'כניסה באמצעות אפל' מאפשרת למשתמשים להפוך את הנתונים שלהם לאנונימיים, כולל כתובת האימייל שלהם, כשהם נכנסים לחשבון. משתמשים שבוחרים באפשרות הזו מקבלים כתובות אימייל עם הדומיין privaterelay.appleid.com
. כשמשתמשים בתכונה 'כניסה באמצעות Apple' באפליקציה, צריך לפעול בהתאם לכללי המדיניות או לתנאים הרלוונטיים למפתחים של Apple בנוגע למזהי Apple האנונימיים האלה.
הדבר כולל קבלת הסכמה נדרשת מהמשתמשים לפני שמשייכים פרטים אישיים מזהים ישירות למזהה Apple אנונימי. כשמשתמשים באימות ב-Firebase, הפעולות האלה עשויות לכלול את הפעולות הבאות:
- קישור של כתובת אימייל ל-Apple ID שעבר אנונימיזציה או להפך.
- קישור של מספר טלפון ל-Apple ID אנונימי או להיפך
- לקשר פרטי כניסה לרשתות חברתיות שלא עברו אנונימיזציה (פייסבוק, Google וכו') למזהה Apple שעבר אנונימיזציה או להיפך.
הרשימה שלמעלה היא חלקית. כדי לוודא שהאפליקציה עומדת בדרישות של Apple, אפשר לעיין בהסכם הרישיון של Apple Developer Program בקטע Membership בחשבון הפיתוח.
גישה לכיתה firebase::auth::Auth
המחלקות Auth
הן שער לכל הקריאות ל-API.
- מוסיפים את קובצי הכותרות Auth ו-App:
#include "firebase/app.h" #include "firebase/auth.h"
- יוצרים מחלקה
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__)
- רוכשים את הכיתה
firebase::auth::Auth
עבורfirebase::App
. יש מיפוי של אחד לאחד ביןApp
לביןAuth
.firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);
טיפול בתהליך הכניסה באמצעות Firebase SDK
תהליך הכניסה באמצעות Apple משתנה בין פלטפורמות Apple ו-Android.
בפלטפורמות של Apple
מאמתים את המשתמשים באמצעות Firebase דרך Apple Sign In Objective-C SDK שמופעל מקוד C++.
לכל בקשת כניסה, יוצרים מחרוזת אקראית – 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--; } } } }
תשלחו את גיבוב ה-SHA256 של המספר האקראי עם בקשת הכניסה שלכם, ו-Apple תעביר אותו ללא שינוי בתגובה. מערכת Firebase מאמתת את התגובה על ידי גיבוב של ה-nonce המקורי והשוואה שלו לערך שמועבר על ידי Apple.
מתחילים את תהליך הכניסה של אפל, כולל הגיבוב (hash) של ה-nonce באמצעות SHA256 ומחלקת הנציגים שתטפל בתגובה של אפל (ראו את השלב הבא):
- (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; }
צריך לטפל בתגובה של אפל בהטמעה של ASAuthorizationControllerDelegate`. אם הכניסה לחשבון הצליחה, צריך להשתמש בטוקן המזהה מהתגובה של אפל עם ה-nonce הלא מגובב כדי לבצע אימות באמצעות 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); } }
משתמשים במחרוזת האסימון ובערך ה-nonce המקורי כדי ליצור Firebase Credential ולהיכנס ל-Firebase.
firebase::auth::OAuthProvider::GetCredential( /*provider_id=*/"apple.com", token, nonce, /*access_token=*/nullptr); firebase::Future<firebase::auth::AuthResult> result = auth->SignInAndRetrieveDataWithCredential(credential);
אפשר להשתמש באותו דפוס עם
Reauthenticate
כדי לאחזר פרטי כניסה עדכניים לפעולות רגישות שדורשות כניסה עדכנית.firebase::Future<firebase::auth::AuthResult> result = user->Reauthenticate(credential);
אפשר להשתמש באותו דפוס כדי לקשר חשבון לכניסה באמצעות חשבון אפל. עם זאת, יכול להיות שתיתקלו בשגיאה אם חשבון Firebase קיים כבר קושר לחשבון אפל שאליו אתם מנסים לקשר. במקרה כזה, העתיד יחזיר סטטוס של
kAuthErrorCredentialAlreadyInUse
והשדהAuthResult
עשוי להכיל ערךcredential
תקין. אפשר להשתמש בהרשאה הזו כדי להיכנס לחשבון שמקושר ל-Apple דרךSignInAndRetrieveDataWithCredential
בלי ליצור עוד אסימון וערך חד-פעמי של 'כניסה באמצעות Apple'.firebase::Future<firebase::auth::AuthResult> link_result = auth->current_user().LinkWithCredential(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() ->additional_user_info.updated_credential.is_valid()) { // Sign In with the new credential firebase::Future<firebase::auth::AuthResult> result = auth->SignInAndRetrieveDataWithCredential( link_result.result()->additional_user_info.updated_credential); } else { // Another link error occurred. }
ב-Android
ב-Android, אפשר לאמת את המשתמשים באמצעות Firebase על ידי שילוב של כניסה כללית מבוססת-אינטרנט באמצעות OAuth באפליקציה באמצעות Firebase SDK כדי לבצע את תהליך הכניסה מקצה לקצה.
כדי לטפל בתהליך הכניסה באמצעות Firebase SDK, פועלים לפי השלבים הבאים:
יוצרים מופע של
FederatedOAuthProviderData
שמוגדר עם מזהה הספק שמתאים ל-Apple.firebase::auth::FederatedOAuthProviderData provider_data("apple.com");
אופציונלי: מציינים היקפי הרשאות נוספים של OAuth 2.0 מעבר לברירת המחדל שרוצים לבקש מספק האימות.
provider_data.scopes.push_back("email"); provider_data.scopes.push_back("name");
אופציונלי: אם רוצים להציג את מסך הכניסה של אפל בשפה שאינה אנגלית, מגדירים את הפרמטר
locale
. במסמכים בנושא 'כניסה באמצעות Apple' מפורטים הלוקאלים הנתמכים.// Localize to French. provider_data.custom_parameters["language"] = "fr"; ```
אחרי שמגדירים את נתוני הספק, משתמשים בהם כדי ליצור FederatedOAuthProvider.
// Construct a FederatedOAuthProvider for use in Auth methods. firebase::auth::FederatedOAuthProvider provider(provider_data);
מתבצע אימות באמצעות Firebase באמצעות אובייקט ספק האימות. שימו לב: בניגוד לפעולות אחרות של FirebaseAuth, הפעולה הזו תשתלט על ממשק המשתמש על ידי הצגת תצוגת אינטרנט שבה המשתמש יכול להזין את פרטי הכניסה שלו.
כדי להתחיל את תהליך הכניסה, קוראים לפונקציה
signInWithProvider
:firebase::Future<firebase::auth::AuthResult> result = auth->SignInWithProvider(provider_data);
האפליקציה יכולה להמתין או לרשום קריאה חוזרת ב-Future.
אפשר להשתמש באותו דפוס עם
ReauthenticateWithProvider
כדי לאחזר פרטי כניסה עדכניים לפעולות רגישות שדורשות כניסה עדכנית.firebase::Future<firebase::auth::AuthResult> result = user.ReauthenticateWithProvider(provider_data);
אחרי זה, יכול להיות שהאפליקציה תמתין או תרשום קריאה חוזרת ב-Future.
בנוסף, אפשר להשתמש ב-
LinkWithCredential()
כדי לקשר ספקי זהויות שונים לחשבונות קיימים.חשוב לזכור שחברת אפל דורשת לקבל מהמשתמשים הסכמה מפורשת לפני שמקשרים את החשבונות שלהם ב-Apple לנתונים אחרים.
לדוגמה, כדי לקשר חשבון פייסבוק לחשבון Firebase הנוכחי, משתמשים באסימון הגישה שקיבלתם מהתחברות המשתמש לפייסבוק:
// 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::AuthResult> result = auth.current_user().LinkWithCredential(credential);
כניסה באמצעות 'הערות' של אפל
בניגוד לספקים אחרים שנתמכים על ידי Firebase Auth, Apple לא מספקת כתובת URL של תמונה.
בנוסף, אם המשתמש בוחר לא לשתף את כתובת האימייל שלו עם האפליקציה, אפל מספקת למשתמש כתובת אימייל ייחודית (בפורמט xyz@privaterelay.appleid.com
) ומשתפת אותה עם האפליקציה שלכם. אם הגדרתם את שירות העברת האימייל הפרטי, אפל מעבירה את האימיילים שנשלחים לכתובת האנונימית לכתובת האימייל האמיתית של המשתמש.
Apple משתפת מידע על המשתמשים, כמו השם לתצוגה, רק עם אפליקציות שבהן המשתמש נכנס לחשבון בפעם הראשונה. בדרך כלל, Firebase שומר את שם התצוגה בפעם הראשונה שמשתמש נכנס לחשבון באמצעות Apple, ואפשר לקבל אותו באמצעות current_user().display_name()
. עם זאת, אם השתמשתם בעבר ב-Apple כדי לאפשר למשתמש להיכנס לאפליקציה בלי להשתמש ב-Firebase, Apple לא תספק ל-Firebase את השם המוצג של המשתמש.
השלבים הבאים
אחרי שהמשתמש נכנס לחשבון בפעם הראשונה, נוצר חשבון משתמש חדש שמקושר לפרטי הכניסה – כלומר, שם המשתמש והסיסמה, מספר הטלפון או פרטי ספק האימות – שבאמצעותם המשתמש נכנס לחשבון. החשבון החדש הזה מאוחסן כחלק מפרויקט Firebase, ואפשר להשתמש בו כדי לזהות משתמש בכל אפליקציה בפרויקט, בלי קשר לשיטת הכניסה של המשתמש.באפליקציות, אפשר לקבל את פרטי הפרופיל הבסיסיים של המשתמש מאובייקט firebase::auth::User
. איך מנהלים משתמשים
בכללי האבטחה של Firebase Realtime Database ו-Cloud Storage, אפשר לקבל את מזהה המשתמש הייחודי של המשתמש המחובר מהמשתנה auth, ולהשתמש בו כדי לשלוט בנתונים שהמשתמש יכול לגשת אליהם.