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

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

قبل ان تبدأ

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

انضم إلى برنامج Apple Developer

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

قم بتكوين تسجيل الدخول مع Apple

يجب تمكين Apple Sign In وتكوينه بشكل صحيح في مشروع 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 class

فئة 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 class for your 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 ++ الخاص بك.

  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 لـ nonce مع طلب تسجيل الدخول الخاص بك ، والذي ستمرره Apple دون تغيير في الاستجابة. يتحقق Firebase من الاستجابة عن طريق تجزئة الأصل nonce ومقارنته بالقيمة التي تم تمريرها بواسطة 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 مع 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);
          }
        }
    
  4. استخدم سلسلة الرمز المميز الناتجة وعلامة nonce الأصلية لإنشاء بيانات اعتماد Firebase وتسجيل الدخول إلى Firebase.

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

    firebase::Future<firebase::auth::SignInResult> result =
        user->Reauthenticate(credential);
    
  6. يمكن استخدام نفس النمط لربط حساب بـ Apple Sign In. ومع ذلك ، قد تواجه خطأ عندما تم بالفعل ربط حساب Firebase موجود بحساب Apple الذي تحاول الارتباط به. عند حدوث ذلك ، سيعيد المستقبل حالة kAuthErrorCredentialAlreadyInUse وقد يحتوي كائن UserInfo الخاص بـ SignInResult على ملف اعتماد updated_credential صالح. يمكن استخدام بيانات الاعتماد هذه لتسجيل الدخول إلى الحساب المرتبط بـ Apple عبر SignInWithCredential دون الحاجة إلى إنشاء رمز مميز آخر لتسجيل الدخول من Apple.

    لاحظ أنه يجب عليك استخدام LinkAndRetrieveDataWithCredential لهذه العملية لاحتواء بيانات الاعتماد نظرًا لأن updated_credential هي عضو في كائن SignInResult.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.
    }
    

على Android

على 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::SignInResult> result =
      auth->SignInWithProvider(provider_data);
    

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

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

    firebase::Future<firebase::auth::SignInResult> 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::SignInResult> result =
        auth.getCurrentUser().linkWithCredential(credential);
    

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

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

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

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

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

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

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

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