المصادقة باستخدام Apple وC++

يمكنك السماح للمستخدمين بالمصادقة مع Firebase باستخدام معرّف Apple من خلال باستخدام Firebase SDK لتنفيذ عملية تسجيل الدخول من خلال بروتوكول OAuth 2.0 الشامل.

قبل البدء

لتسجيل دخول المستخدمين باستخدام Apple، يجب أولاً ضبط ميزة "تسجيل الدخول باستخدام حساب Apple" على موقع مطور Apple، ثم قم بتمكين Apple كموفر تسجيل الدخول إلى مشروع على Firebase.

الانضمام إلى برنامج مطوّري برامج Apple

لا يمكن إعداد ميزة "تسجيل الدخول باستخدام حساب Apple" إلا من خلال أعضاء مطوّر برامج Apple. Google for Startups Cloud Program.

ضبط ميزة "تسجيل الدخول باستخدام حساب Apple"

يجب تفعيل ميزة "تسجيل الدخول إلى Apple" وضبطها بشكل صحيح في مشروع Firebase. تختلف الإعدادات باختلاف النظام الأساسي Android وApple. يُرجى اتّباع "ضبط تسجيل الدخول باستخدام حساب Apple" في أنظمة Apple الأساسية و/أو إرشادات Android قبل المتابعة.

تفعيل Apple كموفِّر لتسجيل الدخول

  1. في وحدة تحكُّم Firebase، افتح قسم المصادقة. في علامة التبويب طريقة تسجيل الدخول، تفعيل مزوِّد خدمة Apple.
  2. اضبط إعدادات موفّر خدمة "تسجيل الدخول إلى Apple":
    1. إذا كنت تنشر تطبيقك على أنظمة Apple الأساسية فقط، يمكنك مغادرة حقول معرّف الخدمة ومعرّف فريق Apple والمفتاح الخاص ورقم تعريف المفتاح فارغة.
    2. للحصول على الدعم على أجهزة Android:
      1. أضِف Firebase إلى مشروع Android. كن يُرجى التأكّد من تسجيل توقيع SHA-1 لتطبيقك عند إعداده في وحدة تحكّم "Firebase"
      2. في Firebase وحدة التحكم، افتح قسم المصادقة. في علامة التبويب طريقة تسجيل الدخول، تفعيل مزوِّد خدمة Apple. حدِّد رقم تعريف الخدمة الذي أنشأته في القسم السابق. بالإضافة إلى ذلك، في قسم إعداد تدفق رمز OAuth، تحديد معرّف فريق Apple والمفتاح الخاص ومعرّف المفتاح اللذين أنشأتهما في القسم السابق.

الالتزام بمتطلبات البيانات المخفية الهوية من Apple

تتيح ميزة "تسجيل الدخول باستخدام حساب Apple" للمستخدمين خيار إخفاء هوية بياناتهم، بما في ذلك عنوان بريده الإلكتروني عند تسجيل الدخول. المستخدمون الذين يحدّدون هذا الخيار لديهم عناوين بريد إلكتروني ضمن النطاق privaterelay.appleid.com. فعندما استخدام ميزة "تسجيل الدخول باستخدام حساب Apple" في تطبيقك، عليك الالتزام بأي سياسات المطوّرين أو البنود من Apple بخصوص أجهزة Apple المجهولة الهوية هذه المعرفات.

ويشمل ذلك الحصول على أي موافقة مطلوبة من المستخدم قبل ربط أي معلومات شخصية تحدد الهوية مباشرة بمعلومات Apple مجهولة رقم التعريف عند استخدام مصادقة Firebase، قد يشمل ذلك ما يلي: الإجراءات:

  • ربط عنوان بريد إلكتروني بمعرّف Apple مجهول الهوية أو العكس بالعكس.
  • ربط رقم هاتف بمعرّف Apple مجهول الهوية أو العكس
  • ربط بيانات اعتماد غير مجهولة الهوية (Facebook، Google، وما إلى ذلك) معرف Apple مجهول أو العكس.

إنّ القائمة أعلاه ليست شاملة. مراجعة برنامج مطوّري برامج Apple اتفاقية الترخيص في قسم "الاشتراك" في حساب المطوِّر لتقديم التأكّد من أنّ تطبيقك يستوفي متطلبات Apple

الوصول إلى الصف firebase::auth::Auth

الفئة Auth هي مدخل جميع طلبات البيانات من واجهة برمجة التطبيقات.
  1. إضافة ملفات رؤوس التطبيقات والمصادقة:
    #include "firebase/app.h"
    #include "firebase/auth.h"
  2. في رمز الإعداد، أنشئ صف واحد (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__)
  3. الحصول على الصف firebase::auth::Auth لـ firebase::App هناك ربط واحد لواحد بين App وAuth.
    firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);

معالجة عملية تسجيل الدخول باستخدام حزمة تطوير البرامج (SDK) لمنصّة Firebase

تختلف عملية تسجيل الدخول باستخدام حساب Apple باختلاف أنظمة Apple وAndroid الأساسية.

على منصات Apple

مصادقة المستخدمين باستخدام Firebase عبر Apple Sign In تم استدعاء حِزمة تطوير البرامج (SDK) الخاصة بـ Objective-C من رمز C++ الخاص بك.

  1. لكل طلب تسجيل دخول، أنشئ سلسلة عشوائية "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 من صحة الردّ. من خلال تجزئة القيمة الأصلية ومقارنتها بالقيمة التي تحققها Apple.

  2. ابدأ خطوات تسجيل الدخول إلى Apple، بما في ذلك في طلبك تجزئة SHA256 الجزء الخاص بالمؤسسة وفئة التفويض التي ستتعامل مع رد Apple (راجع الخطوة التالية):

      - (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;
      }
    
  3. التعامل مع استجابة Apple عند تنفيذ ASPermissionControllerControllerنسي. إذا تم تسجيل الدخول بنجاح، استخدِم رقم التعريف. رمز مميز من استجابة Apple مع جزء غير مجزأ للمصادقة مع 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);
          }
        }
    
  4. استخدام سلسلة الرمز المميّز الناتجة وقيمة الحقل الأصلية لإنشاء Firebase بيانات الاعتماد وتسجيل الدخول إلى Firebase.

    firebase::auth::OAuthProvider::GetCredential(
            /*provider_id=*/"apple.com", token, nonce,
            /*access_token=*/nullptr);
    
    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInAndRetrieveDataWithCredential(credential);
    
  5. يمكن استخدام النمط نفسه مع Reauthenticate الذي يمكن تُستخدم لاسترداد بيانات اعتماد جديدة للعمليات الحساسة التي تتطلب تسجيل دخول حديث.

    firebase::Future<firebase::auth::AuthResult> result =
        user->Reauthenticate(credential);
    
  6. يمكن استخدام النمط نفسه لربط حساب باستخدام ميزة "تسجيل الدخول إلى Apple". ومع ذلك، قد تواجه خطأً عندما يتضمن حساب حالي على Firebase سبق أن تم ربط حساب Apple الذي تحاول الربط به. عندما يحدث ذلك، سيعرض المستقبل حالة قد يحتوي كل من 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" العام إلى تطبيقك باستخدام حزمة تطوير البرامج (SDK) لمنصّة Firebase لتنفيذ إنهاء عملية تسجيل الدخول.

لمعالجة عملية تسجيل الدخول باستخدام حزمة تطوير البرامج (SDK) لمنصّة Firebase، اتّبِع الخطوات التالية:

  1. إنشاء مثيل لـ FederatedOAuthProviderData تم ضبطه باستخدام معرف الموفر المناسب لشركة Apple.

    firebase::auth::FederatedOAuthProviderData provider_data("apple.com");
    
  2. اختياري: حدِّد نطاقات OAuth 2.0 إضافية غير النطاق التلقائي الذي ترغب في طلبها من مُقدِّم خدمة المصادقة.

    provider_data.scopes.push_back("email");
    provider_data.scopes.push_back("name");
    
  3. اختياري: إذا كنت تريد عرض شاشة تسجيل الدخول في Apple بلغة بخلاف الإنجليزية، اضبط المعلمة locale. يمكنك الاطّلاع على تسجيل الدخول باستخدام مستندات Apple للغات المدعومة.

    // Localize to French.
    provider_data.custom_parameters["language"] = "fr";
    ```
    
  4. بعد ضبط بيانات مزوِّد الخدمة، يمكنك استخدامها لإنشاء OAuthProvider.

    // Construct a FederatedOAuthProvider for use in Auth methods.
    firebase::auth::FederatedOAuthProvider provider(provider_data);
    
  5. يمكنك المصادقة مع Firebase باستخدام عنصر موفّر المصادقة. لاحظ أنه على عكس عمليات FirebaseAuth الأخرى، سيتحكم هذا في واجهة المستخدم من خلال فرقعة عرض ويب يمكن للمستخدم من خلاله إدخال بيانات الاعتماد.

    لبدء عملية تسجيل الدخول، يمكنك الاتصال بالرقم signInWithProvider:

    firebase::Future<firebase::auth::AuthResult> result =
      auth->SignInWithProvider(provider_data);
    

    قد ينتظر طلبك بعد ذلك أو تسجيل طلب معاودة الاتصال في المستقبل

  6. يمكن استخدام النمط نفسه مع ReauthenticateWithProvider الذي يمكن تُستخدم لاسترداد بيانات اعتماد جديدة للعمليات الحساسة التي تتطلب تسجيل دخول حديث.

    firebase::Future<firebase::auth::AuthResult> result =
      user.ReauthenticateWithProvider(provider_data);
    

    قد ينتظر تطبيقك بعد ذلك أو يسجّل معاودة الاتصال على المستقبل.

  7. ويمكنك استخدام LinkWithCredential() لربط موفِّري هوية مختلفين. بالحسابات الحالية.

    ملاحظة: تشترط Apple الحصول على موافقة صريحة من المستخدمين قبل وربط حساباتهم على Apple ببيانات أخرى.

    على سبيل المثال، لربط حساب Facebook بحساب Firebase الحالي، استخدم رمز الدخول الذي حصلت عليه من تسجيل دخول المستخدم إلى 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::AuthResult> result =
        auth.current_user().LinkWithCredential(credential);
    

تسجيل الدخول باستخدام Apple Notes

على عكس موفّري الخدمات الآخرين المعتمَدين من خلال مصادقة Firebase، لا توفّر Apple عنوان URL للصورة.

أيضًا، عندما يختار المستخدم عدم مشاركة بريده الإلكتروني مع التطبيق، فإن Apple عنوان بريد إلكتروني فريد لهذا المستخدم (للنموذج xyz@privaterelay.appleid.com)، والذي تتم مشاركته مع تطبيقك إذا كنت هي خدمة ترحيل البريد الإلكتروني الخاص، تعيد Apple توجيه الرسائل الإلكترونية المرسلة إلى العنوان المجهول إلى عنوان البريد الإلكتروني الحقيقي للمستخدم.

لا تشارك Apple معلومات المستخدم إلا، مثل الاسم المعروض، مع التطبيقات في المرة الأولى التي يسجّل فيها المستخدم الدخول. عادةً ما يخزن Firebase الاسم المعروض في المرة الأولى التي يسجّل فيها المستخدم الدخول باستخدام Apple، وهو ما يمكنك الحصول عليه من خلال current_user().display_name() ومع ذلك، إذا سبق لك استخدام Apple لتوقيع مستخدم إلى التطبيق بدون استخدام Firebase، فلن توفر Apple الاسم المعروض للمستخدم.

الخطوات التالية

بعد تسجيل المستخدم الدخول لأول مرة، يتم إنشاء حساب مستخدم جديد المرتبطة ببيانات الاعتماد - أي اسم المستخدم وكلمة المرور أو رقم الهاتف أو معلومات مقدم خدمة المصادقة - المستخدم الذي سجّل الدخول من خلاله. يتم تخزين هذا الحساب الجديد باعتباره جزءًا من مشروع Firebase، ويمكن استخدامها لتحديد هوية مستخدم في كل تطبيقك في مشروعك، بغض النظر عن كيفية تسجيل دخول المستخدم.

في تطبيقاتك، يمكنك الحصول على معلومات الملف الشخصي الأساسية للمستخدم من عنصر firebase::auth::User. عرض إدارة المستخدمين:

في "قاعدة بيانات Firebase في الوقت الفعلي" و"قواعد أمان Cloud Storage"، يمكنك الحصول على رقم تعريف المستخدم الفريد للمستخدم الذي سجّل الدخول من متغير المصادقة، ويستخدمه للتحكم في البيانات التي يمكن للمستخدم الوصول إليها.