اصالت‌سنجی بااستفاده از Apple و C++‎

می‌توانید به کاربران اجازه دهید بااستفاده از Apple ID خودشان با Firebase اصالت‌سنجی کنند، برای این کار باید از «کیت توسعه نرم‌افزار Firebase» برای انجام جریان ورود به سیستم سرتاسر OAuth 2.0 استفاده کنید.

قبل از شروع

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

به «برنامه توسعه‌دهندگان Apple» بپیوندید

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

پیکربندی «ورود به سیستم با Apple»

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

فعال کردن Apple به‌عنوان ارائه‌دهنده ورود به سیستم

  1. در کنسول Firebase، به امنیت > اصالت‌سنجی بروید.
  2. در زبانه روش ورود به سیستم، ارائه‌دهنده ورود به سیستم Apple را فعال کنید.
  3. تنظیمات ارائه‌دهنده «ورود به سیستم با Apple» را پیکربندی کنید:
    • Apple: اگر برنامه خود را فقط در پلاتفرم‌های Apple پیاده‌سازی می‌کنید، می‌توانید فیلدهای «شناسه سرویس»، «شناسه تیم Apple»، «کلید خصوصی»، و «شناسه کلید» را خالی بگذارید.
    • Android: برای پشتیبانی از دستگاه‌های Android، موارد زیر را تکمیل کنید:
      1. ‫Firebase را به پروژه Android خود اضافه کنید.
      2. اگر قبلاً اثر انگشت SHA-1 برنامه‌تان را مشخص نکرده‌اید، آن را مشخص کنید.
        1. در کنسول Firebase، به تنظیمات > زبانه کلی بروید.
        2. به کارت برنامه‌های شما پیمایش کنید، برنامه Android خود را انتخاب کنید، و اثر انگشت SHA-1 خود را در فیلد اثر انگشت‌های گواهینامه SHA اضافه کنید.

        برای جزئیات مربوط به نحوه دریافت اثر انگشت SHA برنامه، اصالت‌سنجی مشتری را ببینید.

      3. تنظیمات ارائه‌دهنده «ورود به سیستم با Apple» را پیکربندی کنید:
        1. در کنسول Firebase، به امنیت > اصالت‌سنجی بروید.
        2. در برگه روش ورود به سیستم، روی ارائه‌دهنده ورود به سیستم Apple کلیک کنید.
        3. «شناسه سرویس» را که در بخش قبلی ایجاد کرده‌اید مشخص کنید. همچنین، در بخش پیکربندی جریان کد OAuth، «شناسه تیم Apple» و کلید خصوصی و شناسه کلیدی را که در بخش قبلی ایجاد کرده‌اید مشخص کنید.

از الزامات داده‌های ناشناس‌سازی‌شده Apple پیروی کنید

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

این شامل دریافت رضایت کاربر موردنیاز قبل‌از قراردادن هرگونه اطلاعات شخصی که مستقیماً شناسایی‌کننده است درارتباط با «شناسه Apple» ناشناس‌سازی‌شده می‌شود. هنگام استفاده از «اصالت‌سنجی Firebase»، این ممکن است شامل اقدامات زیر باشد:

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

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

دسترسی به کلاس firebase::auth::Auth

کلاس Auth دروازه همه فراخوانی‌های API است.
  1. فایل‌های سرصفحه Auth و App را اضافه کنید:
    #include <cassert>
    #include <cstdint>
    
    #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»

فرایند «ورود به سیستم با Apple» در پلاتفرم‌های Apple و Android متفاوت است.

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

کاربرانتان را با Firebase ازطریق «ورود به سیستم Apple» کیت توسعه نرم‌افزار Objective-C که از کد 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 مقدار یک‌بارمصرف و کلاس نماینده‌ای که پاسخ 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 Credential و ورود به سیستم 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، با ادغام کردن «ورود به سیستم OAuth» عمومی مبتنی بر وب در برنامه‌تان بااستفاده از «کیت توسعه نرم‌افزار Firebase»، کاربران را با Firebase اصالت‌سنجی کنید تا جریان ورود به سیستم سرتاسری را انجام دهید.

برای مدیریت جریان ورود به سیستم با «کیت توسعه نرم‌افزار 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. پس‌از پیکربندی داده‌های ارائه‌دهنده، از آن برای ایجاد 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);
    

ورود به سیستم با «یادداشت‌های Apple»

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

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

‫Apple فقط اطلاعات کاربر مثل نام نمایشی را در اولین ورود کاربر به سیستم با برنامه‌ها هم‌رسانی می‌کند. معمولاً Firebase نام نمایشی را اولین‌باری که کاربر با Apple وارد سیستم می‌شود ذخیره می‌کند که می‌توانید آن را با current_user().display_name() دریافت کنید. بااین‌حال، اگر قبلاً از Apple برای ورود به سیستم کاربر در برنامه بدون استفاده از Firebase استفاده کرده باشید، Apple نام نمایشی کاربر را به Firebase ارائه نخواهد داد.

مراحل بعدی

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

در برنامه‌هایتان، می‌توانید اطلاعات نمایه پایه کاربر را از firebase::auth::User شیء دریافت کنید. به مدیریت کاربران مراجعه کنید.

در «قوانین امنیتی» «پایگاه داده بی‌درنگ Firebase» و «فضای ذخیره‌سازی ابری»، می‌توانید شناسه کاربر یکتای کاربر واردشده به سیستم را از متغیر auth دریافت کنید و از آن برای کنترل داده‌هایی که کاربر می‌تواند به آن‌ها دسترسی داشته باشد استفاده کنید.