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

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

قبل البدء

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

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

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

ضبط ميزة "تسجيل الدخول باستخدام حساب 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 عبر حزمة تطوير البرامج (SDK) الخاصة بـ "تسجيل الدخول إلى Apple" والتي تم استدعاؤها من رمز C++ الخاص بك.

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

      - (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 من nonce والفئة المفوَّضة التي ستتعامل مع رد 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. استخدم سلسلة الرمز المميز الناتجة ورقم nonce الأصلي لإنشاء بيانات اعتماد 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. بعد ضبط بيانات موفّر الخدمة، يمكنك استخدامها لإنشاء Federated 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

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

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

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

الخطوات اللاحقة

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

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

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