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

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

قبل ان تبدأ

لتسجيل دخول المستخدمين باستخدام Apple، قم أولاً بتكوين تسجيل الدخول باستخدام Apple على موقع مطور Apple، ثم قم بتمكين Apple كموفر تسجيل دخول لمشروع Firebase الخاص بك.

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

لا يمكن تكوين تسجيل الدخول باستخدام Apple إلا من خلال أعضاء برنامج Apple Developer .

تكوين تسجيل الدخول مع 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 Developer في قسم العضوية في حساب المطور الخاص بك للتأكد من أن تطبيقك يلبي متطلبات Apple.

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

فئة Auth هي البوابة لجميع استدعاءات API.
  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);
    

تعامل مع تدفق تسجيل الدخول باستخدام Firebase SDK

تختلف عملية تسجيل الدخول باستخدام Apple عبر منصات Apple وAndroid.

على منصات أبل

قم بمصادقة المستخدمين لديك باستخدام Firebase عبر Apple Sign In Objective-C SDK الذي تم استدعاؤه من كود 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 للرقم 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 في تنفيذ ASAuthorizationControllerDelegate`. إذا تم تسجيل الدخول بنجاح، استخدم رمز المعرف من استجابة 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 Sign In. ومع ذلك، قد تواجه خطأً عندما يكون حساب Firebase موجودًا مرتبطًا بالفعل بحساب Apple الذي تحاول الارتباط به. عندما يحدث هذا، سيُرجع المستقبل حالة kAuthErrorCredentialAlreadyInUse وقد تحتوي AuthResult على credential صالحة. يمكن استخدام بيانات الاعتماد هذه لتسجيل الدخول إلى الحساب المرتبط بـ Apple عبر SignInAndRetrieveDataWithCredential دون الحاجة إلى إنشاء رمز مميز آخر لتسجيل الدخول إلى Apple وnonce.

    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، قم بمصادقة المستخدمين لديك باستخدام Firebase من خلال دمج تسجيل دخول OAuth العام المستند إلى الويب في تطبيقك باستخدام Firebase SDK لتنفيذ تدفق تسجيل الدخول الشامل.

للتعامل مع تدفق تسجيل الدخول باستخدام Firebase SDK، اتبع الخطوات التالية:

  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. بمجرد تكوين بيانات المزود الخاص بك، استخدمها لإنشاء FederatedOAuthProvider.

    // 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);
    

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

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

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

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

  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);
    

تسجيل الدخول باستخدام ملاحظات أبل

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

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

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

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

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

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

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