ตรวจสอบสิทธิ์โดยใช้ Apple และ C++

คุณอนุญาตให้ผู้ใช้ตรวจสอบสิทธิ์กับ Firebase โดยใช้ Apple ID ได้โดยทำดังนี้ โดยใช้ Firebase SDK เพื่อดำเนินการขั้นตอนการลงชื่อเข้าใช้ 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 Console ให้เปิดส่วน Auth ในแท็บวิธีการลงชื่อเข้าใช้ เปิดใช้ผู้ให้บริการ Apple ระบุรหัสบริการที่คุณสร้าง ส่วนก่อนหน้า นอกจากนี้ในส่วนการกำหนดค่าโฟลว์ของรหัส OAuth ระบุ Apple Team ID ของคุณ และรหัสส่วนตัวและรหัสคีย์ที่คุณสร้างขึ้น ในส่วนก่อนหน้า

ปฏิบัติตามข้อกำหนดด้านข้อมูลที่ไม่ระบุตัวบุคคลของ Apple

ฟีเจอร์ลงชื่อเข้าใช้ด้วย Apple ช่วยให้ผู้ใช้เลือกลบข้อมูลระบุตัวบุคคลได้ รวมถึงอีเมลเมื่อลงชื่อเข้าใช้ ผู้ใช้ที่เลือกตัวเลือกนี้ มีที่อยู่อีเมลในโดเมน privaterelay.appleid.com วันและเวลา หากใช้ฟีเจอร์ลงชื่อเข้าใช้ด้วย Apple ในแอป คุณจะต้องปฏิบัติตาม นโยบายหรือข้อกำหนดสำหรับนักพัฒนาซอฟต์แวร์จาก Apple เกี่ยวกับ Apple ที่มีการลบข้อมูลระบุตัวบุคคลเหล่านี้ รหัส

ซึ่งรวมถึงการได้รับความยินยอมที่จำเป็นจากผู้ใช้ก่อนคุณ เชื่อมโยงข้อมูลส่วนบุคคลที่ระบุตัวบุคคลนั้นได้โดยตรงกับ Apple ที่มีการลบข้อมูลระบุตัวบุคคล ID เมื่อใช้การตรวจสอบสิทธิ์ Firebase อาจรวมถึงสิ่งต่อไปนี้ การดำเนินการ:

  • ลิงก์อีเมลกับ Apple ID ที่ไม่ระบุตัวตนหรือในทางกลับกัน
  • ลิงก์หมายเลขโทรศัพท์กับ Apple ID ที่ไม่ระบุตัวตนหรือในทางกลับกัน
  • ลิงก์ข้อมูลเข้าสู่ระบบโซเชียลที่ระบุตัวบุคคลไม่ได้ (Facebook, Google ฯลฯ) กับ Apple ID ที่ไม่ระบุตัวตนหรือในทางกลับกัน

รายการด้านบนเป็นเพียงตัวอย่างบางส่วนเท่านั้น เข้าร่วมโปรแกรมนักพัฒนาซอฟต์แวร์ของ Apple ข้อตกลงการอนุญาตให้ใช้สิทธิในส่วนการเป็นสมาชิกของบัญชีนักพัฒนาแอป ให้แอปของคุณเป็นไปตามข้อกำหนดของ Apple

เข้าถึงชั้นเรียน 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

ขั้นตอนในการลงชื่อเข้าใช้ด้วย Apple จะแตกต่างกันไปในแพลตฟอร์มของ Apple และ Android ทั้งหมด

ในแพลตฟอร์ม Apple

ตรวจสอบสิทธิ์ผู้ใช้ด้วย Firebase ผ่าน Apple Sign In มีการเรียกใช้ SDK Objective-C จากโค้ด 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 ที่มีค่าที่ได้จากการแฮชที่ไม่ได้แฮชเพื่อตรวจสอบสิทธิ์ 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 Sign In ได้ แต่คุณอาจพบข้อผิดพลาดเมื่อบัญชี Firebase ที่มีอยู่ มีการลิงก์กับบัญชี Apple ที่คุณพยายามจะลิงก์อยู่แล้ว หากเหตุการณ์นี้เกิดขึ้นในอนาคตจะคืนค่าสถานะ kAuthErrorCredentialAlreadyInUse และ AuthResult อาจมี credential ข้อมูลเข้าสู่ระบบนี้ใช้เพื่อลงชื่อเข้าใช้ในที่ลิงก์กับ Apple ได้ บัญชีผ่าน SignInAndRetrieveDataWithCredential ได้โดยไม่จำเป็นต้อง สร้างโทเค็น Apple Sign In และ 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

ใน 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 อื่นๆ ขั้นตอนนี้จะควบคุม UI ของคุณด้วยการ เป็นมุมมองเว็บที่ผู้ใช้สามารถป้อนข้อมูลเข้าสู่ระบบได้

    หากต้องการเริ่มขั้นตอนการลงชื่อเข้าใช้ โปรดโทรหา 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 ไม่เหมือนกับผู้ให้บริการรายอื่นๆ ที่ Firebase Auth รองรับ URL ของภาพถ่าย

นอกจากนี้ เมื่อผู้ใช้เลือกที่จะไม่แชร์อีเมลกับแอป Apple ให้ที่อยู่อีเมลที่ไม่ซ้ำกันสำหรับผู้ใช้ดังกล่าว (ในแบบฟอร์ม xyz@privaterelay.appleid.com) ซึ่งแชร์กับแอปของคุณ หากคุณ กำหนดค่าบริการส่งต่ออีเมลส่วนตัวแล้ว Apple จะส่งต่ออีเมลที่ส่งไปยัง กับอีเมลจริงของผู้ใช้

Apple จะแชร์เฉพาะข้อมูลผู้ใช้ เช่น ชื่อที่แสดงกับแอป ครั้งแรกที่ผู้ใช้ลงชื่อเข้าใช้ โดยทั่วไป Firebase จะจัดเก็บชื่อที่แสดง ครั้งแรกที่ผู้ใช้ลงชื่อเข้าใช้ด้วย Apple ซึ่งคุณจะใช้ current_user().display_name(). แต่หากคุณเคยใช้ Apple ในการลงนาม ผู้ใช้ไปยังแอปโดยไม่ใช้ Firebase นั้น Apple จะไม่ให้บริการ Firebase ชื่อที่แสดงของผู้ใช้

ขั้นตอนถัดไป

หลังจากผู้ใช้ลงชื่อเข้าใช้เป็นครั้งแรก ระบบจะสร้างบัญชีผู้ใช้ใหม่ และ ซึ่งเชื่อมโยงกับข้อมูลเข้าสู่ระบบ ซึ่งก็คือชื่อผู้ใช้และรหัสผ่าน หมายเลขโทรศัพท์ หรือ ข้อมูลของผู้ให้บริการการตรวจสอบสิทธิ์ - ผู้ใช้ที่ลงชื่อเข้าใช้ บัญชีใหม่นี้จะจัดเก็บเป็น ส่วนหนึ่งของโปรเจ็กต์ Firebase ของคุณ ซึ่งใช้เพื่อระบุผู้ใช้ในทุก แอปในโปรเจ็กต์ของคุณได้ ไม่ว่าผู้ใช้จะลงชื่อเข้าใช้ด้วยวิธีใด

ในแอป คุณสามารถดูข้อมูลโปรไฟล์พื้นฐานของผู้ใช้ได้จาก ออบเจ็กต์ firebase::auth::User รายการ โปรดดู จัดการผู้ใช้

ในฐานข้อมูลเรียลไทม์ของ Firebase และกฎความปลอดภัยของ Cloud Storage คุณจะได้รับ รหัสผู้ใช้ที่ไม่ซ้ำกันของผู้ใช้ที่ลงชื่อเข้าใช้จากตัวแปรการตรวจสอบสิทธิ์ และใช้เพื่อ ควบคุมข้อมูลที่ผู้ใช้เข้าถึงได้