Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Thêm xác thực đa yếu tố vào ứng dụng iOS của bạn

Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.

Nếu đã nâng cấp lên Xác thực Firebase với Nền tảng nhận dạng, bạn có thể thêm xác thực đa yếu tố SMS vào ứng dụng iOS của mình.

Xác thực đa yếu tố tăng tính bảo mật cho ứng dụng của bạn. Mặc dù những kẻ tấn công thường xâm phạm mật khẩu và tài khoản xã hội, nhưng việc chặn tin nhắn văn bản lại khó khăn hơn.

Trước khi bắt đầu

  1. Cho phép ít nhất một nhà cung cấp hỗ trợ xác thực đa yếu tố. Mọi nhà cung cấp đều hỗ trợ MFA, ngoại trừ xác thực điện thoại, xác thực ẩn danh và Trung tâm trò chơi Apple.

  2. Đảm bảo ứng dụng của bạn đang xác minh email của người dùng. MFA yêu cầu xác minh email. Điều này ngăn các tác nhân độc hại đăng ký dịch vụ bằng email mà họ không sở hữu, sau đó khóa chủ sở hữu thực sự bằng cách thêm yếu tố thứ hai.

Kích hoạt xác thực đa yếu tố

  1. Mở trang Xác thực > Phương thức đăng nhập của bảng điều khiển Firebase.

  2. Trong phần Nâng cao , bật Xác thực đa yếu tố SMS .

    Bạn cũng nên nhập các số điện thoại mà bạn sẽ dùng để thử nghiệm ứng dụng của mình. Mặc dù là tùy chọn, nhưng bạn nên đăng ký số điện thoại thử nghiệm để tránh bị tắc nghẽn trong quá trình phát triển.

  3. Nếu bạn chưa cấp phép cho miền của ứng dụng, hãy thêm miền đó vào danh sách cho phép trên trang Xác thực > Cài đặt của bảng điều khiển Firebase.

Đang xác minh ứng dụng của bạn

Firebase cần xác minh rằng các yêu cầu SMS đến từ ứng dụng của bạn. Bạn có thể làm điều này theo hai cách:

  • Thông báo APN im lặng : Khi bạn đăng nhập người dùng lần đầu tiên, Firebase có thể gửi thông báo đẩy im lặng đến thiết bị của người dùng. Xác thực có thể tiến hành nếu ứng dụng nhận được thông báo. Lưu ý rằng kể từ iOS 8.0, bạn không cần yêu cầu người dùng cho phép thông báo đẩy để sử dụng phương pháp này.

  • xác minh reCAPTCHA : Nếu bạn không thể gửi thông báo im lặng (ví dụ: vì người dùng đã tắt làm mới nền hoặc bạn đang thử nghiệm ứng dụng của mình trong trình giả lập iOS), bạn có thể sử dụng reCAPTCHA. Trong nhiều trường hợp, reCAPTCHA sẽ tự động giải quyết mà không cần sự tương tác của người dùng.

Sử dụng thông báo im lặng

Để bật thông báo APN để sử dụng với Firebase:

  1. Trong Xcode, bật thông báo đẩy cho dự án của bạn.

  2. Tải khóa xác thực APN của bạn lên bằng Bảng điều khiển Firebase (các thay đổi của bạn sẽ tự động chuyển sang Google Cloud Firebase). Nếu bạn chưa có khóa xác thực APN, hãy xem Định cấu hình APN bằng FCM để tìm hiểu cách lấy khóa.

    1. Mở Bảng điều khiển Firebase .

    2. Điều hướng đến Cài đặt dự án .

    3. Chọn tab Nhắn tin qua đám mây .

    4. Trong khóa xác thực APNs , trong phần cấu hình ứng dụng iOS , hãy nhấp vào Tải lên .

    5. Chọn khóa của bạn.

    6. Thêm ID khóa cho khóa. Bạn có thể tìm thấy ID khóa trong Chứng chỉ, Số nhận dạng & Cấu hình trong Trung tâm thành viên dành cho nhà phát triển của Apple .

    7. Nhấp vào Tải lên .

Nếu bạn đã có chứng chỉ APN, bạn có thể tải chứng chỉ lên để thay thế.

Sử dụng xác minh reCAPTCHA

Để cho phép SDK máy khách sử dụng reCAPTCHA:

  1. Mở cấu hình dự án của bạn trong Xcode.

  2. Bấm đúp vào tên dự án trong chế độ xem dạng cây bên trái.

  3. Chọn ứng dụng của bạn từ phần Mục tiêu .

  4. Chọn tab Thông tin .

  5. Mở rộng phần Loại URL .

  6. Nhấp vào nút + .

  7. Nhập ID khách hàng bị đảo ngược của bạn vào trường Lược đồ URL . Bạn có thể tìm thấy giá trị này được liệt kê trong tệp cấu hình GoogleService-Info.plist dưới dạng REVERSED_CLIENT_ID .

Khi hoàn tất, cấu hình của bạn sẽ trông giống như sau:

chương trình tùy chỉnh

Theo tùy chọn, bạn có thể tùy chỉnh cách ứng dụng của mình hiển thị SFSafariViewController hoặc UIWebView khi hiển thị reCAPTCHA. Để thực hiện việc này, hãy tạo một lớp tùy chỉnh phù hợp với giao thức FIRAuthUIDelegate và chuyển nó tới verifyPhoneNumber:UIDelegate:completion: .

Lựa chọn hình thức đăng ký

Bạn có thể chọn xem ứng dụng của mình có yêu cầu xác thực đa yếu tố hay không cũng như cách thức và thời điểm đăng ký người dùng của bạn. Một số mẫu phổ biến bao gồm:

  • Đăng ký yếu tố thứ hai của người dùng như một phần của đăng ký. Sử dụng phương pháp này nếu ứng dụng của bạn yêu cầu xác thực đa yếu tố cho tất cả người dùng. Lưu ý rằng tài khoản phải có địa chỉ email đã được xác minh để đăng ký yếu tố thứ hai, vì vậy quy trình đăng ký của bạn sẽ phải đáp ứng điều này.

  • Cung cấp tùy chọn có thể bỏ qua để đăng ký yếu tố thứ hai trong quá trình đăng ký. Các ứng dụng muốn khuyến khích, nhưng không yêu cầu, xác thực đa yếu tố có thể thích phương pháp này hơn.

  • Cung cấp khả năng thêm yếu tố thứ hai từ trang quản lý hồ sơ hoặc tài khoản của người dùng, thay vì màn hình đăng ký. Điều này giảm thiểu trở ngại trong quá trình đăng ký, trong khi vẫn cung cấp xác thực đa yếu tố cho người dùng nhạy cảm về bảo mật.

  • Yêu cầu tăng dần yếu tố thứ hai khi người dùng muốn truy cập các tính năng có yêu cầu bảo mật cao hơn.

Ghi danh một yếu tố thứ hai

Để đăng ký một yếu tố phụ mới cho người dùng:

  1. Xác thực lại người dùng.

  2. Yêu cầu người dùng nhập số điện thoại của họ.

  3. Nhận phiên đa yếu tố cho người dùng:

    Nhanh

    authResult.user.multiFactor.getSessionWithCompletion() { (session, error) in
      // ...
    }
    

    Mục tiêu-C

    [authResult.user.multiFactor
      getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
                                NSError * _Nullable error) {
        // ...
    }];
    
  4. Gửi tin nhắn xác minh đến điện thoại của người dùng. Đảm bảo số điện thoại được định dạng bằng dấu + ở đầu và không có dấu chấm câu hoặc khoảng trắng nào khác (ví dụ: +15105551234 )

    Nhanh

    // Send SMS verification code.
    PhoneAuthProvider.provider().verifyPhoneNumber(
      phoneNumber,
      uiDelegate: nil,
      multiFactorSession: session) { (verificationId, error) in
        // verificationId will be needed for enrollment completion.
    }
    

    Mục tiêu-C

    // Send SMS verification code.
    [FIRPhoneAuthProvider.provider verifyPhoneNumber:phoneNumber
                                          UIDelegate:nil
                                  multiFactorSession:session
                                          completion:^(NSString * _Nullable verificationID,
                                                        NSError * _Nullable error) {
        // verificationId will be needed for enrollment completion.
    }];
    

    Mặc dù không bắt buộc nhưng cách tốt nhất là thông báo trước cho người dùng rằng họ sẽ nhận được tin nhắn SMS và mức phí tiêu chuẩn sẽ được áp dụng.

    Phương verifyPhoneNumber() bắt đầu quá trình xác minh ứng dụng trong nền bằng cách sử dụng thông báo đẩy im lặng. Nếu không có thông báo đẩy im lặng, thay vào đó, thử thách reCAPTCHA sẽ được đưa ra.

  5. Khi mã SMS được gửi, hãy yêu cầu người dùng xác minh mã. Sau đó, sử dụng phản hồi của họ để tạo PhoneAuthCredential :

    Nhanh

    // Ask user for the verification code. Then:
    let credential = PhoneAuthProvider.provider().credential(
      withVerificationID: verificationId,
      verificationCode: verificationCode)
    

    Mục tiêu-C

    // Ask user for the SMS verification code. Then:
    FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider
                                           credentialWithVerificationID:verificationID
                                           verificationCode:kPhoneSecondFactorVerificationCode];
    
  6. Khởi tạo một đối tượng xác nhận:

    Nhanh

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    Mục tiêu-C

    FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  7. Hoàn thành việc ghi danh. Theo tùy chọn, bạn có thể chỉ định tên hiển thị cho yếu tố thứ hai. Điều này hữu ích cho người dùng có nhiều yếu tố thứ hai, vì số điện thoại bị ẩn trong quy trình xác thực (ví dụ: +1******1234).

    Nhanh

    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    user.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in
      // ...
    }
    

    Mục tiêu-C

    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    [authResult.user.multiFactor enrollWithAssertion:assertion
                                         displayName:nil
                                          completion:^(NSError * _Nullable error) {
        // ...
    }];
    

Đoạn mã dưới đây cho thấy một ví dụ hoàn chỉnh về việc đăng ký yếu tố thứ hai:

Nhanh

let user = Auth.auth().currentUser
user?.multiFactor.getSessionWithCompletion({ (session, error) in
  // Send SMS verification code.
  PhoneAuthProvider.provider().verifyPhoneNumber(
    phoneNumber,
    uiDelegate: nil,
    multiFactorSession: session
  ) { (verificationId, error) in
    // verificationId will be needed for enrollment completion.
    // Ask user for the verification code.
    let credential = PhoneAuthProvider.provider().credential(
      withVerificationID: verificationId!,
      verificationCode: phoneSecondFactorVerificationCode)
    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    user?.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in
      // ...
    }
  }
})

Mục tiêu-C

FIRUser *user = FIRAuth.auth.currentUser;
[user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
                                              NSError * _Nullable error) {
    // Send SMS verification code.
    [FIRPhoneAuthProvider.provider
      verifyPhoneNumber:phoneNumber
      UIDelegate:nil
      multiFactorSession:session
      completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
        // verificationId will be needed for enrollment completion.

        // Ask user for the verification code.
        // ...

        // Then:
        FIRPhoneAuthCredential *credential =
            [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID
                                                        verificationCode:kPhoneSecondFactorVerificationCode];
        FIRMultiFactorAssertion *assertion =
            [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];

        // Complete enrollment. This will update the underlying tokens
        // and trigger ID token change listener.
        [user.multiFactor enrollWithAssertion:assertion
                                  displayName:displayName
                                    completion:^(NSError * _Nullable error) {
            // ...
        }];
    }];
}];

Chúc mừng! Bạn đã đăng ký thành công yếu tố xác thực thứ hai cho người dùng.

Đăng nhập người dùng bằng yếu tố thứ hai

Để đăng nhập người dùng bằng xác minh SMS hai yếu tố:

  1. Đăng nhập người dùng bằng yếu tố đầu tiên của họ, sau đó gặp lỗi cho biết yêu cầu xác thực nhiều yếu tố. Lỗi này chứa trình giải quyết, gợi ý về các yếu tố thứ hai đã đăng ký và phiên cơ bản chứng minh người dùng đã xác thực thành công với yếu tố đầu tiên.

    Ví dụ: nếu yếu tố đầu tiên của người dùng là email và mật khẩu:

    Nhanh

    Auth.auth().signIn(
      withEmail: email,
      password: password
    ) { (result, error) in
      let authError = error as NSError
      if authError?.code == AuthErrorCode.secondFactorRequired.rawValue {
        // The user is a multi-factor user. Second factor challenge is required.
        let resolver =
          authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
        // ...
      } else {
        // Handle other errors such as wrong password.
      }
    }
    

    Mục tiêu-C

    [FIRAuth.auth signInWithEmail:email
                         password:password
                       completion:^(FIRAuthDataResult * _Nullable authResult,
                                    NSError * _Nullable error) {
        if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) {
            // User is not enrolled with a second factor and is successfully signed in.
            // ...
        } else {
            // The user is a multi-factor user. Second factor challenge is required.
        }
    }];
    

    Nếu yếu tố đầu tiên của người dùng là nhà cung cấp được liên kết, chẳng hạn như OAuth, hãy phát hiện lỗi sau khi gọi getCredentialWith() .

  2. Nếu người dùng đăng ký nhiều yếu tố phụ, hãy hỏi họ nên sử dụng yếu tố nào. Bạn có thể lấy số điện thoại bị che dấu bằng resolver.hints[selectedIndex].phoneNumber và tên hiển thị bằng resolver.hints[selectedIndex].displayName .

    Nhanh

    // Ask user which second factor to use. Then:
    if resolver.hints[selectedIndex].factorID == PhoneMultiFactorID {
      // User selected a phone second factor.
      // ...
    } else {
      // Unsupported second factor.
      // Note that only phone second factors are currently supported.
    }
    

    Mục tiêu-C

    FIRMultiFactorResolver *resolver =
        (FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
    
    // Ask user which second factor to use. Then:
    FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex];
    if (hint.factorID == FIRPhoneMultiFactorID) {
      // User selected a phone second factor.
      // ...
    } else {
      // Unsupported second factor.
      // Note that only phone second factors are currently supported.
    }
    
  3. Gửi tin nhắn xác minh đến điện thoại của người dùng:

    Nhanh

    // Send SMS verification code.
    let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo
    PhoneAuthProvider.provider().verifyPhoneNumber(
      with: hint,
      uiDelegate: nil,
      multiFactorSession: resolver.session
    ) { (verificationId, error) in
      // verificationId will be needed for sign-in completion.
    }
    

    Mục tiêu-C

    // Send SMS verification code
    [FIRPhoneAuthProvider.provider
      verifyPhoneNumberWithMultiFactorInfo:hint
      UIDelegate:nil
      multiFactorSession:resolver.session
      completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
        if (error != nil) {
            // Failed to verify phone number.
        }
    }];
    
  4. Khi mã SMS được gửi, hãy yêu cầu người dùng xác minh mã và sử dụng mã đó để tạo PhoneAuthCredential :

    Nhanh

    // Ask user for the verification code. Then:
    let credential = PhoneAuthProvider.provider().credential(
      withVerificationID: verificationId!,
      verificationCode: verificationCodeFromUser)
    

    Mục tiêu-C

    // Ask user for the SMS verification code. Then:
    FIRPhoneAuthCredential *credential =
        [FIRPhoneAuthProvider.provider
          credentialWithVerificationID:verificationID
                      verificationCode:verificationCodeFromUser];
    
  5. Khởi tạo một đối tượng xác nhận với thông tin xác thực:

    Nhanh

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    Mục tiêu-C

    FIRMultiFactorAssertion *assertion =
        [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  6. Giải quyết vấn đề đăng nhập. Sau đó, bạn có thể truy cập kết quả đăng nhập ban đầu, bao gồm thông tin xác thực và dữ liệu dành riêng cho nhà cung cấp tiêu chuẩn:

    Nhanh

    // Complete sign-in. This will also trigger the Auth state listeners.
    resolver.resolveSignIn(with: assertion) { (authResult, error) in
      // authResult will also contain the user, additionalUserInfo, optional
      // credential (null for email/password) associated with the first factor sign-in.
    
      // For example, if the user signed in with Google as a first factor,
      // authResult.additionalUserInfo will contain data related to Google provider that
      // the user signed in with.
    
      // user.credential contains the Google OAuth credential.
      // user.credential.accessToken contains the Google OAuth access token.
      // user.credential.idToken contains the Google OAuth ID token.
    }
    

    Mục tiêu-C

    // Complete sign-in.
    [resolver resolveSignInWithAssertion:assertion
                              completion:^(FIRAuthDataResult * _Nullable authResult,
                                            NSError * _Nullable error) {
        if (error != nil) {
            // User successfully signed in with the second factor phone number.
        }
    }];
    

Mã bên dưới hiển thị một ví dụ hoàn chỉnh về cách đăng nhập người dùng đa yếu tố:

Nhanh

Auth.auth().signIn(
  withEmail: email,
  password: password
) { (result, error) in
  let authError = error as NSError?
  if authError?.code == AuthErrorCode.secondFactorRequired.rawValue {
    let resolver =
      authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver

    // Ask user which second factor to use.
    // ...

    // Then:
    let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo

    // Send SMS verification code
    PhoneAuthProvider.provider().verifyPhoneNumber(
      with: hint,
      uiDelegate: nil,
      multiFactorSession: resolver.session
    ) { (verificationId, error) in
      if error != nil {
        // Failed to verify phone number.
      }
      // Ask user for the SMS verification code.
      // ...

      // Then:
      let credential = PhoneAuthProvider.provider().credential(
        withVerificationID: verificationId!,
        verificationCode: verificationCodeFromUser)
      let assertion = PhoneMultiFactorGenerator.assertion(with: credential)

      // Complete sign-in.
      resolver.resolveSignIn(with: assertion) { (authResult, error) in
        if error != nil {
          // User successfully signed in with the second factor phone number.
        }
      }
    }
  }
}

Mục tiêu-C

[FIRAuth.auth signInWithEmail:email
                     password:password
                   completion:^(FIRAuthDataResult * _Nullable authResult,
                               NSError * _Nullable error) {
    if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) {
        // User is not enrolled with a second factor and is successfully signed in.
        // ...
    } else {
        FIRMultiFactorResolver *resolver =
            (FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];

        // Ask user which second factor to use.
        // ...

        // Then:
        FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex];

        // Send SMS verification code
        [FIRPhoneAuthProvider.provider
          verifyPhoneNumberWithMultiFactorInfo:hint
                                    UIDelegate:nil
                            multiFactorSession:resolver.session
                                    completion:^(NSString * _Nullable verificationID,
                                                NSError * _Nullable error) {
            if (error != nil) {
                // Failed to verify phone number.
            }

            // Ask user for the SMS verification code.
            // ...

            // Then:
            FIRPhoneAuthCredential *credential =
                [FIRPhoneAuthProvider.provider
                  credentialWithVerificationID:verificationID
                              verificationCode:kPhoneSecondFactorVerificationCode];
            FIRMultiFactorAssertion *assertion =
                [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];

            // Complete sign-in.
            [resolver resolveSignInWithAssertion:assertion
                                      completion:^(FIRAuthDataResult * _Nullable authResult,
                                                    NSError * _Nullable error) {
                if (error != nil) {
                    // User successfully signed in with the second factor phone number.
                }
            }];
        }];
    }
}];

Chúc mừng! Bạn đã đăng nhập thành công người dùng bằng xác thực đa yếu tố.

Cái gì tiếp theo