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

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

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

ก่อนจะเริ่ม

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

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

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

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

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

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

  1. บูรณาการเข้าสู่ระบบของ Facebook ใน app ของคุณโดยทำตาม เอกสารของนักพัฒนา เมื่อคุณเริ่มต้น 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. นำเข้าโมดูล Firebase ในของคุณ UIApplicationDelegate :

    Swift

    import Firebase

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

    @import Firebase;
  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 จำกัด

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

  1. บูรณาการเข้าสู่ระบบ Facebook จำกัด ใน app ของคุณโดยทำตาม เอกสารของนักพัฒนา
  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. นำเข้าโมดูล Firebase ในของคุณ UIApplicationDelegate :

    Swift

    import Firebase

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

    @import Firebase;
  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 Unhashed ที่จะได้รับการรับรอง 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 เรียลไทม์และการจัดเก็บเมฆ กฎการรักษาความปลอดภัย , คุณจะได้รับการลงนามใน 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;
}

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