Catch up on everthing we announced at this year's Firebase Summit. Learn more

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

คุณอนุญาตให้ผู้ใช้ตรวจสอบสิทธิ์กับ Firebase โดยใช้ Apple ID ของตนได้โดยใช้ Firebase SDK เพื่อดำเนินการขั้นตอนการลงชื่อเข้าใช้ OAuth 2.0 ตั้งแต่ต้นทางถึงปลายทาง

ก่อนจะเริ่ม

ในการลงชื่อเข้าใช้ผู้ใช้โดยใช้ Apple ก่อนอื่นให้กำหนดค่าการลงชื่อเข้าใช้ด้วย Apple บนเว็บไซต์นักพัฒนาของ Apple จากนั้นเปิดใช้งาน Apple เป็นผู้ให้บริการการลงชื่อเข้าใช้สำหรับโปรเจ็กต์ Firebase ของคุณ

เข้าร่วม Apple Developer Program

เข้าสู่ระบบด้วยแอปเปิ้ลเท่านั้นที่สามารถกำหนดค่าโดยสมาชิกของ แอปเปิ้ลผู้พัฒนาโปรแกรม

กำหนดค่าการลงชื่อเข้าใช้ด้วย Apple

ต้องเปิดใช้งาน Apple Sign In และกำหนดค่าอย่างเหมาะสมในโปรเจ็กต์ Firebase ของคุณ การกำหนดค่าจะแตกต่างกันไปตามแพลตฟอร์ม Android และ Apple โปรดปฏิบัติตาม "กำหนดค่าเข้าสู่ระบบด้วยแอปเปิ้ล" ของ แพลตฟอร์มแอปเปิ้ล และ / หรือ Android คู่มือก่อนดำเนินการต่อ

เปิดใช้งาน Apple เป็นผู้ให้บริการลงชื่อเข้าใช้

  1. ใน Firebase คอนโซล , เปิดส่วนการตรวจสอบสิทธิ์ ที่ลงในแท็บวิธีการที่ช่วยให้ผู้ให้บริการแอปเปิ้ล
  2. กำหนดการตั้งค่าผู้ให้บริการการลงชื่อเข้าใช้ Apple:
    1. หากคุณกำลังปรับใช้แอพของคุณบนแพลตฟอร์ม Apple เท่านั้น คุณสามารถปล่อยให้ช่อง ID บริการ, Apple Team ID, คีย์ส่วนตัว และ ID คีย์ว่างเปล่า
    2. สำหรับการสนับสนุนบนอุปกรณ์ Android:
      1. เพิ่ม Firebase กับโครงการ Android ของคุณ อย่าลืมลงทะเบียนลายเซ็น SHA-1 ของแอปเมื่อคุณตั้งค่าแอปในคอนโซล Firebase
      2. ใน Firebase คอนโซล , เปิดส่วนการตรวจสอบสิทธิ์ ที่ลงในแท็บวิธีการที่ช่วยให้ผู้ให้บริการแอปเปิ้ล ระบุรหัสบริการที่คุณสร้างในส่วนก่อนหน้า นอกจากนี้ ในส่วนการกำหนดค่าโฟลว์โค้ด OAuth ให้ระบุ Apple Team ID และคีย์ส่วนตัวและ ID คีย์ที่คุณสร้างในส่วนก่อนหน้า

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

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

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

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

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

เข้า firebase::auth::Auth ระดับ

Auth ชั้นเป็นประตูสำหรับทุกการเรียก API
  1. เพิ่มการตรวจสอบสิทธิ์และ 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 Objective-C SDK ที่เรียกใช้จากโค้ด C++ ของคุณ

  1. สำหรับคำขอลงชื่อเข้าใช้ทุกครั้ง ให้สร้างสตริงสุ่ม ซึ่งก็คือ "nonce" ซึ่งคุณจะใช้เพื่อให้แน่ใจว่าโทเค็น ID ที่คุณได้รับนั้นได้รับการอนุญาตเป็นการเฉพาะเพื่อตอบสนองต่อคำขอตรวจสอบสิทธิ์ของแอปของคุณ ขั้นตอนนี้มีความสำคัญต่อการป้องกันการโจมตีซ้ำ

      - (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` หากการลงชื่อเข้าใช้สำเร็จ ให้ใช้โทเค็น ID จากการตอบสนองของ 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 ข้อมูลประจำตัวนี้สามารถใช้ในการเข้าสู่ระบบในบัญชีของแอปเปิ้ลเชื่อมโยงผ่าน SignInWithCredential โดยไม่จำเป็นต้องสร้างอีกลงชื่อเข้าใช้แอปเปิ้ลในโทเค็นและขณะปัจจุบัน

    โปรดทราบว่าคุณต้องใช้ 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 ID

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

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

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

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

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

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

ในฐานข้อมูล Firebase Realtime Database และ Cloud Storage Security Rules คุณสามารถรับ ID ผู้ใช้เฉพาะของผู้ใช้ที่ลงชื่อเข้าใช้จากตัวแปร auth และใช้เพื่อควบคุมข้อมูลที่ผู้ใช้สามารถเข้าถึงได้