获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

ตรวจสอบสิทธิ์โดยใช้การเข้าสู่ระบบ Facebook บนแพลตฟอร์ม Apple

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

ก่อนจะเริ่ม

ใช้ Swift Package Manager เพื่อติดตั้งและจัดการการขึ้นต่อกันของ Firebase

  1. ใน Xcode เมื่อโปรเจ็กต์แอปของคุณเปิดอยู่ ให้ไปที่ File > Add Packages
  2. เมื่อได้รับแจ้ง ให้เพิ่มที่เก็บ SDK ของแพลตฟอร์ม Firebase Apple:
  3.   https://github.com/firebase/firebase-ios-sdk
  4. เลือกไลบรารีการตรวจสอบสิทธิ์ Firebase
  5. เมื่อเสร็จแล้ว Xcode จะเริ่มแก้ไขและดาวน์โหลดการพึ่งพาของคุณในพื้นหลังโดยอัตโนมัติ

ถัดไป ดำเนินการขั้นตอนการกำหนดค่าบางอย่าง:

  1. บนไซต์ Facebook for Developers รับ App ID และ App Secret สำหรับแอพของคุณ
  2. เปิดใช้งานการเข้าสู่ระบบ Facebook:
    1. ใน คอนโซล Firebase ให้เปิดส่วนการ ตรวจสอบสิทธิ์
    2. บนแท็บ วิธีการลงชื่อเข้า ใช้ ให้เปิดใช้งานวิธีการลงชื่อเข้าใช้ Facebook และระบุ ID แอพและความลับ ของแอพที่คุณได้รับจาก Facebook
    3. จากนั้น ตรวจสอบให้แน่ใจว่า OAuth เปลี่ยนเส้นทาง URI ของคุณ (เช่น my-app-12345.firebaseapp.com/__/auth/handler ) ถูกระบุว่าเป็นหนึ่งใน OAuth เปลี่ยนเส้นทาง URI ของคุณในหน้าการตั้งค่าของแอพ Facebook บนไซต์ Facebook สำหรับนักพัฒนา ใน ผลิตภัณฑ์ การตั้งค่า > การกำหนดค่าการเข้าสู่ระบบ Facebook

ใช้การเข้าสู่ระบบ Facebook

หากต้องการใช้การเข้าสู่ระบบ Facebook "แบบคลาสสิก" ให้ทำตามขั้นตอนต่อไปนี้ หรือคุณสามารถใช้ Facebook Limited Login ดังที่แสดงในส่วนถัดไป

  1. รวมการเข้าสู่ระบบด้วย Facebook ในแอปของคุณโดยทำตาม เอกสารของผู้พัฒนา เมื่อคุณเริ่มต้นอ็อบเจ็กต์ FBSDKLoginButton ให้ตั้งค่าผู้รับมอบสิทธิ์เพื่อรับเหตุการณ์การเข้าสู่ระบบและออกจากระบบ ตัวอย่างเช่น:

    Swift

    let loginButton = FBSDKLoginButton()
    loginButton.delegate = self
    

    วัตถุประสงค์-C

    FBSDKLoginButton *loginButton = [[FBSDKLoginButton alloc] init];
    loginButton.delegate = self;
    
    ในผู้รับมอบสิทธิ์ของคุณ ให้ใช้งาน didCompleteWithResult:error:

    Swift

    func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
      if let error = error {
        print(error.localizedDescription)
        return
      }
      // ...
    }
    

    วัตถุประสงค์-C

    - (void)loginButton:(FBSDKLoginButton *)loginButton
        didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result
                        error:(NSError *)error {
      if (error == nil) {
        // ...
      } else {
        NSLog(error.localizedDescription);
      }
    }
    
  2. นำเข้าโมดูล FirebaseCore ใน UIApplicationDelegate ของคุณ รวมถึง โมดูล Firebase อื่นๆ ที่ผู้รับมอบสิทธิ์แอปของคุณใช้ ตัวอย่างเช่น ในการใช้ Cloud Firestore และการตรวจสอบสิทธิ์:

    Swift

    import FirebaseCore
    import FirebaseFirestore
    import FirebaseAuth
    // ...
          

    วัตถุประสงค์-C

    @import FirebaseCore;
    @import FirebaseFirestore;
    @import FirebaseAuth;
    // ...
          
  3. กำหนดค่าอินสแตนซ์ที่ใช้ร่วมกันของ FirebaseApp ใน application(_:didFinishLaunchingWithOptions:) ของผู้รับมอบสิทธิ์แอปของคุณ:

    Swift

    // Use Firebase library to configure APIs
    FirebaseApp.configure()

    วัตถุประสงค์-C

    // Use Firebase library to configure APIs
    [FIRApp configure];
  4. หลังจากที่ผู้ใช้ลงชื่อเข้าใช้สำเร็จ ในการใช้งาน didCompleteWithResult:error: รับโทเค็นการเข้าถึงสำหรับผู้ใช้ที่ลงชื่อเข้าใช้และแลกเปลี่ยนเป็นข้อมูลรับรอง Firebase:

    Swift

    let credential = FacebookAuthProvider
      .credential(withAccessToken: AccessToken.current!.tokenString)
    

    วัตถุประสงค์-C

    FIRAuthCredential *credential = [FIRFacebookAuthProvider
        credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
    

ใช้ Facebook Limited Login

ในการใช้ Facebook Limited Login แทนการเข้าสู่ระบบ Facebook "แบบคลาสสิก" ให้ทำตามขั้นตอนต่อไปนี้

  1. รวม Facebook Limited Login เข้ากับแอพของคุณโดยทำตาม เอกสารของผู้พัฒนา
  2. สำหรับคำขอลงชื่อเข้าใช้ทุกครั้ง ให้สร้างสตริงสุ่มที่ไม่ซ้ำกัน นั่นคือ "nonce" ซึ่งคุณจะใช้เพื่อให้แน่ใจว่าโทเค็น ID ที่คุณได้รับนั้นได้รับการอนุญาตเป็นการเฉพาะเพื่อตอบสนองต่อคำขอตรวจสอบสิทธิ์ของแอปของคุณ ขั้นตอนนี้มีความสำคัญต่อการป้องกันการโจมตีซ้ำ คุณสามารถสร้าง nonce ที่ปลอดภัยด้วยการเข้ารหัสด้วย SecRandomCopyBytes(_:_:_) ดังในตัวอย่างต่อไปนี้:

    Swift

    // Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce
    private func randomNonceString(length: Int = 32) -> String {
      precondition(length > 0)
      let charset: [Character] =
        Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._")
      var result = ""
      var remainingLength = length
    
      while remainingLength > 0 {
        let randoms: [UInt8] = (0 ..< 16).map { _ in
          var random: UInt8 = 0
          let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random)
          if errorCode != errSecSuccess {
            fatalError(
              "Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)"
            )
          }
          return random
        }
    
        randoms.forEach { random in
          if remainingLength == 0 {
            return
          }
    
          if random < charset.count {
            result.append(charset[Int(random)])
            remainingLength -= 1
          }
        }
      }
    
      return result
    }
    
            

    วัตถุประสงค์-C

    // Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-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--;
          }
        }
      }
    
      return [result copy];
    }
            
    คุณจะส่งแฮช SHA-256 ของ nonce พร้อมคำขอลงชื่อเข้าใช้ของคุณ ซึ่ง Facebook จะไม่เปลี่ยนคำตอบในการตอบกลับ Firebase ตรวจสอบการตอบกลับโดยแฮช nonce ดั้งเดิมและเปรียบเทียบกับค่าที่ Facebook ส่งผ่าน

    Swift

    @available(iOS 13, *)
    private func sha256(_ input: String) -> String {
      let inputData = Data(input.utf8)
      let hashedData = SHA256.hash(data: inputData)
      let hashString = hashedData.compactMap {
        String(format: "%02x", $0)
      }.joined()
    
      return hashString
    }
    
            

    วัตถุประสงค์-C

    - (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. เมื่อคุณตั้งค่า FBSDKLoginButton ให้ตั้งค่าผู้รับมอบสิทธิ์เพื่อรับเหตุการณ์การเข้าสู่ระบบและออกจากระบบ ตั้งค่าโหมดการติดตามเป็น FBSDKLoginTrackingLimited และแนบ nonce ตัวอย่างเช่น:

    Swift

    func setupLoginButton() {
        let nonce = randomNonceString()
        currentNonce = nonce
        loginButton.delegate = self
        loginButton.loginTracking = .limited
        loginButton.nonce = sha256(nonce)
    }
            

    วัตถุประสงค์-C

    - (void)setupLoginButton {
      NSString *nonce = [self randomNonce:32];
      self.currentNonce = nonce;
      self.loginButton.delegate = self;
      self.loginButton.loginTracking = FBSDKLoginTrackingLimited
      self.loginButton.nonce = [self stringBySha256HashingString:nonce];
    }
            
    ในผู้รับมอบสิทธิ์ของคุณ ให้ใช้งาน didCompleteWithResult:error:

    Swift

    func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
      if let error = error {
        print(error.localizedDescription)
        return
      }
      // ...
    }
            

    วัตถุประสงค์-C

    - (void)loginButton:(FBSDKLoginButton *)loginButton
        didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result
                        error:(NSError *)error {
      if (error == nil) {
        // ...
      } else {
        NSLog(error.localizedDescription);
      }
    }
            
  4. นำเข้าโมดูล FirebaseCore ใน UIApplicationDelegate ของคุณ รวมถึง โมดูล Firebase อื่นๆ ที่ผู้รับมอบสิทธิ์แอปของคุณใช้ ตัวอย่างเช่น ในการใช้ Cloud Firestore และการตรวจสอบสิทธิ์:

    Swift

    import FirebaseCore
    import FirebaseFirestore
    import FirebaseAuth
    // ...
          

    วัตถุประสงค์-C

    @import FirebaseCore;
    @import FirebaseFirestore;
    @import FirebaseAuth;
    // ...
          
  5. กำหนดค่าอินสแตนซ์ที่ใช้ร่วมกันของ FirebaseApp ใน application(_:didFinishLaunchingWithOptions:) ของผู้รับมอบสิทธิ์แอปของคุณ:

    Swift

    // Use Firebase library to configure APIs
    FirebaseApp.configure()

    วัตถุประสงค์-C

    // Use Firebase library to configure APIs
    [FIRApp configure];
  6. หลังจากที่ผู้ใช้ลงชื่อเข้าใช้สำเร็จ ในการใช้งาน didCompleteWithResult:error: ของคุณ ให้ใช้โทเค็น ID จากการตอบสนองของ Facebook ด้วย nonce ที่ยังไม่ได้แฮชเพื่อรับข้อมูลรับรอง Firebase:

    Swift

    // Initialize a Firebase credential.
    let idTokenString = AuthenticationToken.current?.tokenString
    let nonce = currentNonce
    let credential = OAuthProvider.credential(withProviderID: "facebook.com",
                                              idToken: idTokenString!,
                                              rawNonce: nonce)
            

    วัตถุประสงค์-C

    // Initialize a Firebase credential.
    NSString *idTokenString = FBSDKAuthenticationToken.currentAuthenticationToken.tokenString;
    NSString *rawNonce = self.currentNonce;
    FIROAuthCredential *credential = [FIROAuthProvider credentialWithProviderID:@"facebook.com"
                                                                        IDToken:idTokenString
                                                                       rawNonce:rawNonce];
            

ตรวจสอบสิทธิ์ด้วย Firebase

สุดท้าย ตรวจสอบกับ Firebase โดยใช้ข้อมูลรับรอง Firebase:

Swift

Auth.auth().signIn(with: credential) { authResult, error in
    if let error = error {
      let authError = error as NSError
      if isMFAEnabled, authError.code == AuthErrorCode.secondFactorRequired.rawValue {
        // The user is a multi-factor user. Second factor challenge is required.
        let resolver = authError
          .userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
        var displayNameString = ""
        for tmpFactorInfo in resolver.hints {
          displayNameString += tmpFactorInfo.displayName ?? ""
          displayNameString += " "
        }
        self.showTextInputPrompt(
          withMessage: "Select factor to sign in\n\(displayNameString)",
          completionBlock: { userPressedOK, displayName in
            var selectedHint: PhoneMultiFactorInfo?
            for tmpFactorInfo in resolver.hints {
              if displayName == tmpFactorInfo.displayName {
                selectedHint = tmpFactorInfo as? PhoneMultiFactorInfo
              }
            }
            PhoneAuthProvider.provider()
              .verifyPhoneNumber(with: selectedHint!, uiDelegate: nil,
                                 multiFactorSession: resolver
                                   .session) { verificationID, error in
                if error != nil {
                  print(
                    "Multi factor start sign in failed. Error: \(error.debugDescription)"
                  )
                } else {
                  self.showTextInputPrompt(
                    withMessage: "Verification code for \(selectedHint?.displayName ?? "")",
                    completionBlock: { userPressedOK, verificationCode in
                      let credential: PhoneAuthCredential? = PhoneAuthProvider.provider()
                        .credential(withVerificationID: verificationID!,
                                    verificationCode: verificationCode!)
                      let assertion: MultiFactorAssertion? = PhoneMultiFactorGenerator
                        .assertion(with: credential!)
                      resolver.resolveSignIn(with: assertion!) { authResult, error in
                        if error != nil {
                          print(
                            "Multi factor finanlize sign in failed. Error: \(error.debugDescription)"
                          )
                        } else {
                          self.navigationController?.popViewController(animated: true)
                        }
                      }
                    }
                  )
                }
              }
          }
        )
      } else {
        self.showMessagePrompt(error.localizedDescription)
        return
      }
      // ...
      return
    }
    // User is signed in
    // ...
}
    

วัตถุประสงค์-C

[[FIRAuth auth] signInWithCredential:credential
                          completion:^(FIRAuthDataResult * _Nullable authResult,
                                       NSError * _Nullable error) {
    if (isMFAEnabled && error && error.code == FIRAuthErrorCodeSecondFactorRequired) {
      FIRMultiFactorResolver *resolver = error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
      NSMutableString *displayNameString = [NSMutableString string];
      for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
        [displayNameString appendString:tmpFactorInfo.displayName];
        [displayNameString appendString:@" "];
      }
      [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Select factor to sign in\n%@", displayNameString]
                           completionBlock:^(BOOL userPressedOK, NSString *_Nullable displayName) {
       FIRPhoneMultiFactorInfo* selectedHint;
       for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
         if ([displayName isEqualToString:tmpFactorInfo.displayName]) {
           selectedHint = (FIRPhoneMultiFactorInfo *)tmpFactorInfo;
         }
       }
       [FIRPhoneAuthProvider.provider
        verifyPhoneNumberWithMultiFactorInfo:selectedHint
        UIDelegate:nil
        multiFactorSession:resolver.session
        completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
          if (error) {
            [self showMessagePrompt:error.localizedDescription];
          } else {
            [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Verification code for %@", selectedHint.displayName]
                                 completionBlock:^(BOOL userPressedOK, NSString *_Nullable verificationCode) {
             FIRPhoneAuthCredential *credential =
                 [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID
                                                              verificationCode:verificationCode];
             FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
             [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
               if (error) {
                 [self showMessagePrompt:error.localizedDescription];
               } else {
                 NSLog(@"Multi factor finanlize sign in succeeded.");
               }
             }];
           }];
          }
        }];
     }];
    }
  else if (error) {
    // ...
    return;
  }
  // User successfully signed in. Get user data from the FIRUser object
  if (authResult == nil) { return; }
  FIRUser *user = authResult.user;
  // ...
}];
    

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

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

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

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

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

หากต้องการออกจากระบบผู้ใช้ ให้โทรออกจาก signOut:

Swift

    let firebaseAuth = Auth.auth()
do {
  try firebaseAuth.signOut()
} catch let signOutError as NSError {
  print("Error signing out: %@", signOutError)
}
  

วัตถุประสงค์-C

    NSError *signOutError;
BOOL status = [[FIRAuth auth] signOut:&signOutError];
if (!status) {
  NSLog(@"Error signing out: %@", signOutError);
  return;
}

คุณอาจต้องการเพิ่มรหัสการจัดการข้อผิดพลาดสำหรับข้อผิดพลาดในการตรวจสอบสิทธิ์ทั้งหมด ดูการ จัดการข้อผิดพลาด