Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now

با استفاده از Apple و C++ احراز هویت

با مجموعه‌ها، منظم بمانید ذخیره و دسته‌بندی محتوا براساس اولویت‌های شما.

می‌توانید با استفاده از Firebase SDK برای انجام جریان ورود به سیستم OAuth 2.0 به کاربران خود اجازه دهید با Firebase احراز هویت با استفاده از Apple ID خود انجام دهند.

قبل از اینکه شروع کنی

برای ورود به سیستم کاربرانی که از اپل استفاده می کنند، ابتدا Sign In with Apple را در سایت توسعه دهنده اپل پیکربندی کنید، سپس Apple را به عنوان ارائه دهنده ورود به سیستم برای پروژه Firebase خود فعال کنید.

به برنامه توسعه دهندگان اپل بپیوندید

ورود به سیستم با Apple فقط توسط اعضای برنامه توسعه دهنده Apple قابل پیکربندی است.

پیکربندی ورود با اپل

Apple Sign In باید در پروژه Firebase شما فعال و به درستی پیکربندی شود. پیکربندی در پلتفرم های اندروید و اپل متفاوت است. لطفاً قبل از ادامه، بخش «پیکربندی ورود به سیستم با اپل» را در پلتفرم‌های اپل و/یا راهنمای Android دنبال کنید.

اپل را به عنوان ارائه دهنده ورود فعال کنید

  1. در کنسول Firebase ، بخش Auth را باز کنید. در برگه روش ورود ، ارائه دهنده اپل را فعال کنید.
  2. تنظیمات ارائه دهنده Apple Sign-in را پیکربندی کنید:
    1. اگر برنامه خود را فقط در پلتفرم‌های اپل اجرا می‌کنید، می‌توانید قسمت‌های شناسه سرویس، شناسه تیم اپل، کلید خصوصی و شناسه کلید را خالی بگذارید.
    2. برای پشتیبانی در دستگاه های اندروید:
      1. Firebase را به پروژه اندروید خود اضافه کنید . هنگام تنظیم برنامه خود در کنسول Firebase، حتماً امضای SHA-1 برنامه خود را ثبت کنید.
      2. در کنسول Firebase ، بخش Auth را باز کنید. در برگه روش ورود ، ارائه دهنده اپل را فعال کنید. شناسه سرویسی که در قسمت قبل ایجاد کردید را مشخص کنید. همچنین در قسمت OAuth code flow configuration ID Apple Team و شناسه کلید خصوصی و کلیدی که در قسمت قبل ایجاد کرده اید را مشخص کنید.

الزامات داده های ناشناس اپل را رعایت کنید

ورود به سیستم با اپل به کاربران این امکان را می دهد که هنگام ورود به سیستم، داده های خود، از جمله آدرس ایمیل خود را ناشناس نشان دهند. کاربرانی که این گزینه را انتخاب می کنند، آدرس های ایمیل با دامنه privaterelay.appleid.com . هنگامی که از ورود با اپل در برنامه خود استفاده می کنید، باید از هر گونه خط مشی یا شرایط توسعه دهنده قابل اجرا از طرف Apple در مورد این شناسه های ناشناس اپل پیروی کنید.

این شامل اخذ هرگونه رضایت کاربر مورد نیاز قبل از مرتبط کردن هر گونه اطلاعات شخصی شناسایی مستقیم با یک شناسه ناشناس اپل است. هنگام استفاده از Firebase Authentication، این ممکن است شامل اقدامات زیر باشد:

  • یک آدرس ایمیل را به یک Apple ID ناشناس پیوند دهید یا برعکس.
  • یک شماره تلفن را به یک Apple ID ناشناس پیوند دهید یا برعکس
  • یک اعتبار اجتماعی غیر ناشناس (فیس بوک، گوگل و غیره) را به یک شناسه ناشناس اپل پیوند دهید یا بالعکس.

فهرست فوق کامل نیست. به توافقنامه مجوز برنامه توسعه دهنده اپل در بخش عضویت حساب توسعه دهنده خود مراجعه کنید تا مطمئن شوید برنامه شما با الزامات اپل مطابقت دارد.

دسترسی به firebase::auth::Auth

کلاس Auth دروازه همه تماس های API است.
  1. فایل‌های هدر Auth و App را اضافه کنید:
    #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، جریان ورود به سیستم را مدیریت کنید

فرآیند ورود به سیستم با اپل در پلتفرم های اپل و اندروید متفاوت است.

در پلتفرم های اپل

کاربران خود را با 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 را همراه با درخواست ورود خود ارسال می‌کنید که اپل در پاسخ آن را بدون تغییر ارسال می‌کند. Firebase پاسخ را با هش کردن nonce اصلی و مقایسه آن با مقدار ارسال شده توسط Apple تأیید می کند.

  2. جریان ورود به سیستم اپل را شروع کنید، از جمله در درخواست خود هش SHA256 از nonce و کلاس نماینده که پاسخ اپل را مدیریت می کند (مرحله بعدی را ببینید):

      - (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. در اجرای ASAuthorizationControllerDelegate، پاسخ اپل را مدیریت کنید. اگر ورود به سیستم با موفقیت انجام شد، برای احراز هویت با 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 از رشته توکن به دست آمده و nonce اصلی استفاده کنید.

    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 Sign In دیگر استفاده کرد.

    توجه داشته باشید که برای این عملیات باید از 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، با ادغام ورود OAuth عمومی مبتنی بر وب به برنامه خود با استفاده از Firebase SDK برای انجام جریان ورود به سیستم، کاربران خود را با Firebase احراز هویت کنید.

برای مدیریت جریان ورود به سیستم با Firebase SDK، این مراحل را دنبال کنید:

  1. نمونه ای از FederatedOAuthProviderData پیکربندی شده با شناسه ارائه دهنده مناسب برای اپل بسازید.

    firebase::auth::FederatedOAuthProviderData provider_data("apple.com");
    
  2. اختیاری: دامنه های OAuth 2.0 اضافی را فراتر از پیش فرضی که می خواهید از ارائه دهنده احراز هویت درخواست کنید، مشخص کنید.

    provider_data.scopes.push_back("email");
    provider_data.scopes.push_back("name");
    
  3. اختیاری: اگر می خواهید صفحه ورود اپل به زبانی غیر از انگلیسی نمایش داده شود، پارامتر locale را تنظیم کنید. برای مناطق پشتیبانی شده، به اسناد ورود با اپل مراجعه کنید.

    // 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. با استفاده از شی ارائه دهنده Auth با Firebase احراز هویت کنید. توجه داشته باشید که بر خلاف سایر عملیات FirebaseAuth، با نمایش یک نمای وب که در آن کاربر می‌تواند اعتبار خود را وارد کند، رابط کاربری شما را کنترل می‌کند.

    برای شروع جریان ورود به سیستم، signInWithProvider :

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

    سپس درخواست شما ممکن است منتظر بماند یا یک تماس برگشتی در Future ثبت کند.

  6. همین الگو را می توان با ReauthenticateWithProvider استفاده کرد که می تواند برای بازیابی اعتبارنامه های جدید برای عملیات حساسی که نیاز به ورود اخیر دارند استفاده شود.

    firebase::Future<firebase::auth::SignInResult> result =
      user->ReauthenticateWithProvider(provider_data);
    

    سپس درخواست شما ممکن است منتظر بماند یا یک تماس برگشتی در Future ثبت کند.

  7. و، می توانید از linkWithCredential() برای پیوند دادن ارائه دهندگان هویت مختلف به حساب های موجود استفاده کنید.

    توجه داشته باشید که اپل از شما می‌خواهد قبل از اینکه حساب‌های اپل آن‌ها را به داده‌های دیگر مرتبط کنید، رضایت صریح را از کاربران دریافت کنید.

    به عنوان مثال، برای پیوند دادن یک حساب فیس بوک به حساب فعلی 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::SignInResult> result =
        auth.getCurrentUser().linkWithCredential(credential);
    

با Apple Notes وارد شوید

برخلاف سایر ارائه دهندگان پشتیبانی شده توسط Firebase Auth، اپل URL عکس ارائه نمی دهد.

همچنین، وقتی کاربر تصمیم می‌گیرد ایمیل خود را با برنامه به اشتراک نگذارد، اپل یک آدرس ایمیل منحصربه‌فرد برای آن کاربر ارائه می‌کند (به شکل xyz@privaterelay.appleid.com )، که آن را با برنامه شما به اشتراک می‌گذارد. اگر سرویس ارسال ایمیل خصوصی را پیکربندی کرده باشید، اپل ایمیل های ارسال شده به آدرس ناشناس را به آدرس ایمیل واقعی کاربر فوروارد می کند.

اپل تنها اولین باری که کاربر وارد سیستم می شود، اطلاعات کاربر مانند نام نمایشی را با برنامه ها به اشتراک می گذارد. معمولاً، Firebase نام نمایشی را در اولین باری که کاربر با اپل وارد می شود، ذخیره می کند، که می توانید با getCurrentUser().getDisplayName() دریافت کنید. با این حال، اگر قبلاً از اپل برای ورود کاربر به برنامه بدون استفاده از Firebase استفاده کرده‌اید، اپل نام نمایشی کاربر را به Firebase ارائه نمی‌کند.

مراحل بعدی

پس از اینکه کاربر برای اولین بار وارد سیستم شد، یک حساب کاربری جدید ایجاد می‌شود و به اعتبارنامه‌ها (یعنی نام کاربری و رمز عبور، شماره تلفن یا اطلاعات ارائه‌دهنده تاییدیه) مرتبط می‌شود که کاربر با آن وارد شده است. این حساب جدید به‌عنوان بخشی از پروژه Firebase شما ذخیره می‌شود و می‌توان از آن برای شناسایی کاربر در همه برنامه‌های پروژه‌تان، صرف نظر از نحوه ورود کاربر به سیستم استفاده کرد.

در برنامه های خود، می توانید اطلاعات اولیه پروفایل کاربر را از firebase::auth::user object دریافت کنید. به مدیریت کاربران مراجعه کنید.

در قوانین امنیتی Firebase Realtime Database و Cloud Storage، می‌توانید شناسه کاربری منحصربه‌فرد کاربر واردشده به سیستم را از متغیر auth دریافت کنید و از آن برای کنترل داده‌هایی که کاربر می‌تواند به آن دسترسی داشته باشد استفاده کنید.