Xác thực với Firebase bằng liên kết email trên nền tảng Apple

Bạn có thể sử dụng Xác thực Firebase để đăng nhập người dùng bằng cách gửi cho họ email chứa liên kết mà họ có thể nhấp vào để đăng nhập. Trong quá trình này, địa chỉ email của người dùng cũng được xác minh.

Có rất nhiều lợi ích khi đăng nhập bằng email:

  • Đăng ký và đăng nhập ít ma sát.
  • Giảm nguy cơ sử dụng lại mật khẩu trên các ứng dụng, điều này có thể làm suy yếu tính bảo mật của ngay cả những mật khẩu được chọn kỹ càng.
  • Khả năng xác thực người dùng đồng thời xác minh rằng người dùng đó là chủ sở hữu hợp pháp của địa chỉ email.
  • Người dùng chỉ cần có tài khoản email có thể truy cập để đăng nhập. Không cần quyền sở hữu số điện thoại hoặc tài khoản mạng xã hội.
  • Người dùng có thể đăng nhập an toàn mà không cần cung cấp (hoặc ghi nhớ) mật khẩu, điều này có thể gây cồng kềnh trên thiết bị di động.
  • Người dùng hiện tại trước đây đã đăng nhập bằng mã nhận dạng email (mật khẩu hoặc liên kết) có thể được nâng cấp để đăng nhập chỉ bằng email. Ví dụ: người dùng quên mật khẩu vẫn có thể đăng nhập mà không cần đặt lại mật khẩu.

Trước khi bắt đầu

Sử dụng Trình quản lý gói Swift để cài đặt và quản lý các phần phụ thuộc của Firebase.

  1. Trong Xcode, khi dự án ứng dụng của bạn đang mở, hãy điều hướng đến File > Add Packages .
  2. Khi được nhắc, hãy thêm kho lưu trữ SDK nền tảng Firebase của Apple:
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. Chọn thư viện Xác thực Firebase.
  5. Thêm cờ -ObjC vào phần Cờ liên kết khác trong cài đặt bản dựng của mục tiêu của bạn.
  6. Khi hoàn tất, Xcode sẽ tự động bắt đầu phân giải và tải xuống các phần phụ thuộc của bạn ở chế độ nền.

Để đăng nhập người dùng bằng liên kết email, trước tiên bạn phải kích hoạt nhà cung cấp Email và phương thức đăng nhập liên kết Email cho dự án Firebase của mình:

  1. Trong bảng điều khiển Firebase , hãy mở phần Xác thực .
  2. Trên tab Phương thức đăng nhập , bật nhà cung cấp Email/Mật khẩu . Lưu ý rằng tính năng đăng nhập bằng email/mật khẩu phải được bật để sử dụng tính năng đăng nhập bằng liên kết email.
  3. Trong cùng một phần, bật phương thức đăng nhập liên kết Email (đăng nhập không cần mật khẩu) .
  4. Nhấp vào để lưu .

Để bắt đầu luồng xác thực, hãy hiển thị cho người dùng một giao diện nhắc người dùng cung cấp địa chỉ email của họ, sau đó gọi sendSignInLink để yêu cầu Firebase gửi liên kết xác thực đến email của người dùng.

  1. Xây dựng đối tượng ActionCodeSettings , đối tượng này cung cấp cho Firebase các hướng dẫn về cách tạo liên kết email. Đặt các trường sau:

    • url: Liên kết sâu để nhúng và bất kỳ trạng thái bổ sung nào sẽ được chuyển qua. Miền của liên kết phải được đưa vào danh sách trắng trong danh sách các miền được ủy quyền của Bảng điều khiển Firebase. Bạn có thể tìm thấy miền này bằng cách đi tới tab Phương thức đăng nhập (Xác thực -> Phương thức đăng nhập).
    • iOSBundleID và androidPackageName : Các ứng dụng sẽ sử dụng khi liên kết đăng nhập được mở trên thiết bị Android hoặc Apple. Tìm hiểu thêm về cách định cấu hình Liên kết động Firebase để mở liên kết hành động email qua ứng dụng dành cho thiết bị di động.
    • handCodeInApp: Đặt thành true. Thao tác đăng nhập phải luôn được hoàn thành trong ứng dụng, không giống như các hành động email khác ngoài nhóm (đặt lại mật khẩu và xác minh email). Điều này là do ở cuối quy trình, người dùng dự kiến ​​sẽ đăng nhập và trạng thái Xác thực của họ vẫn tồn tại trong ứng dụng.
    • DynamicLinkDomain: Khi xác định nhiều miền liên kết động tùy chỉnh cho một dự án, hãy chỉ định miền nào sẽ sử dụng khi liên kết được mở thông qua một ứng dụng di động được chỉ định (ví dụ: example.page.link ). Nếu không, tên miền đầu tiên sẽ tự động được chọn.

    Nhanh

    let actionCodeSettings = ActionCodeSettings()
    actionCodeSettings.url = URL(string: "https://www.example.com")
    // The sign-in operation has to always be completed in the app.
    actionCodeSettings.handleCodeInApp = true
    actionCodeSettings.setIOSBundleID(Bundle.main.bundleIdentifier!)
    actionCodeSettings.setAndroidPackageName("com.example.android",
                                             installIfNotAvailable: false, minimumVersion: "12")
    

    Mục tiêu-C

    FIRActionCodeSettings *actionCodeSettings = [[FIRActionCodeSettings alloc] init];
    [actionCodeSettings setURL:[NSURL URLWithString:@"https://www.example.com"]];
    // The sign-in operation has to always be completed in the app.
    actionCodeSettings.handleCodeInApp = YES;
    [actionCodeSettings setIOSBundleID:[[NSBundle mainBundle] bundleIdentifier]];
    [actionCodeSettings setAndroidPackageName:@"com.example.android"
                        installIfNotAvailable:NO
                               minimumVersion:@"12"];
    

    Để tìm hiểu thêm về ActionCodeSettings, hãy tham khảo phần Trạng thái chuyển trong phần Hành động email .

  2. Hỏi người dùng email của họ.

  3. Gửi liên kết xác thực đến email của người dùng và lưu email của người dùng trong trường hợp người dùng hoàn tất đăng nhập email trên cùng một thiết bị.

    Nhanh

    Auth.auth().sendSignInLink(toEmail: email,
                               actionCodeSettings: actionCodeSettings) { error in
      // ...
        if let error = error {
          self.showMessagePrompt(error.localizedDescription)
          return
        }
        // The link was successfully sent. Inform the user.
        // Save the email locally so you don't need to ask the user for it again
        // if they open the link on the same device.
        UserDefaults.standard.set(email, forKey: "Email")
        self.showMessagePrompt("Check your email for link")
        // ...
    }
    

    Mục tiêu-C

    [[FIRAuth auth] sendSignInLinkToEmail:email
                       actionCodeSettings:actionCodeSettings
                               completion:^(NSError *_Nullable error) {
      // ...
        if (error) {
          [self showMessagePrompt:error.localizedDescription];
           return;
        }
        // The link was successfully sent. Inform the user.
        // Save the email locally so you don't need to ask the user for it again
        // if they open the link on the same device.
        [NSUserDefaults.standardUserDefaults setObject:email forKey:@"Email"];
        [self showMessagePrompt:@"Check your email for link"];
        // ...
    }];
    

Mối lo ngại về an ninh

Để ngăn việc sử dụng liên kết đăng nhập để đăng nhập với tư cách là người dùng ngoài ý muốn hoặc trên một thiết bị ngoài ý muốn, Firebase Auth yêu cầu cung cấp địa chỉ email của người dùng khi hoàn tất quy trình đăng nhập. Để đăng nhập thành công, địa chỉ email này phải khớp với địa chỉ mà liên kết đăng nhập được gửi ban đầu.

Bạn có thể hợp lý hóa quy trình này cho những người dùng mở liên kết đăng nhập trên cùng thiết bị mà họ yêu cầu liên kết bằng cách lưu trữ cục bộ địa chỉ email của họ khi bạn gửi email đăng nhập. Sau đó, sử dụng địa chỉ này để hoàn thành quy trình.

Sau khi hoàn tất đăng nhập, mọi cơ chế đăng nhập chưa được xác minh trước đó sẽ bị xóa khỏi người dùng và mọi phiên hiện có sẽ bị vô hiệu. Ví dụ: nếu trước đây ai đó đã tạo một tài khoản chưa được xác minh có cùng email và mật khẩu thì mật khẩu của người dùng sẽ bị xóa để ngăn người mạo danh đã xác nhận quyền sở hữu và tạo tài khoản chưa được xác minh đó đăng nhập lại bằng cùng một tài khoản.

Hoàn tất đăng nhập vào ứng dụng di động của Apple

Xác thực Firebase sử dụng Liên kết động Firebase để gửi liên kết email đến thiết bị di động. Để hoàn tất đăng nhập qua ứng dụng di động, ứng dụng phải được định cấu hình để phát hiện liên kết ứng dụng đến, phân tích liên kết sâu cơ bản rồi hoàn tất đăng nhập.

Firebase Auth sử dụng Liên kết động Firebase khi gửi liên kết được mở trong ứng dụng di động. Để sử dụng tính năng này, Liên kết động cần được định cấu hình trong Bảng điều khiển Firebase.

  1. Kích hoạt Liên kết động Firebase:

    1. Trong bảng điều khiển Firebase , hãy mở phần Liên kết động .
    2. Nếu bạn chưa chấp nhận các điều khoản của Liên kết động và đã tạo miền Liên kết động, hãy thực hiện ngay bây giờ.

      Nếu bạn đã tạo miền Liên kết động, hãy lưu ý đến nó. Miền Liên kết động thường trông giống như ví dụ sau:

      example.page.link

      Bạn sẽ cần giá trị này khi định cấu hình ứng dụng Apple hoặc Android của mình để chặn liên kết đến.

  2. Cấu hình ứng dụng Apple:

    1. Nếu bạn dự định xử lý các liên kết này từ ứng dụng của mình thì ID gói cần phải được chỉ định trong cài đặt dự án Bảng điều khiển Firebase. Ngoài ra, ID App Store và ID nhóm nhà phát triển Apple cũng cần được chỉ định.
    2. Bạn cũng sẽ cần định cấu hình miền xử lý hành động email của mình dưới dạng Miền liên kết trong các khả năng của ứng dụng. Theo mặc định, trình xử lý tác vụ email được lưu trữ trên một miền như ví dụ sau:
      APP_ID.firebaseapp.com
    3. Nếu dự định phân phối ứng dụng của mình cho iOS phiên bản 8 trở xuống, bạn sẽ cần đặt ID gói của mình làm lược đồ tùy chỉnh cho các URL đến.
    4. Để biết thêm về điều này, hãy tham khảo Hướng dẫn nhận liên kết động nền tảng Apple .

Sau khi bạn nhận được liên kết như mô tả ở trên, hãy xác minh rằng liên kết đó dùng để xác thực liên kết email và hoàn tất đăng nhập.

Nhanh

if Auth.auth().isSignIn(withEmailLink: link) {
        Auth.auth().signIn(withEmail: email, link: self.link) { user, error in
          // ...
        }
}

Mục tiêu-C

if ([[FIRAuth auth] isSignInWithEmailLink:link]) {
    [[FIRAuth auth] signInWithEmail:email
                               link:link
                         completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
      // ...
    }];
}

Để tìm hiểu về cách xử lý đăng nhập bằng liên kết email trong ứng dụng Android, hãy tham khảo hướng dẫn Android .

Để tìm hiểu về cách xử lý việc đăng nhập bằng liên kết email trong ứng dụng web, hãy tham khảo Hướng dẫn web .

Bạn cũng có thể liên kết phương thức xác thực này với người dùng hiện có. Ví dụ: người dùng đã được xác thực trước đó với nhà cung cấp khác, chẳng hạn như số điện thoại, có thể thêm phương thức đăng nhập này vào tài khoản hiện có của họ.

Sự khác biệt sẽ nằm ở nửa sau của hoạt động:

Nhanh

  let credential = EmailAuthCredential.credential(withEmail:email
                                                       link:link)
  Auth.auth().currentUser?.link(with: credential) { authData, error in
    if (error) {
      // And error occurred during linking.
      return
    }
    // The provider was successfully linked.
    // The phone user can now sign in with their phone number or email.
  }

Mục tiêu-C

  FIRAuthCredential *credential =
      [FIREmailAuthProvider credentialWithEmail:email link:link];
  [FIRAuth auth].currentUser
      linkWithCredential:credential
              completion:^(FIRAuthDataResult *_Nullable result,
                           NSError *_Nullable error) {
    if (error) {
      // And error occurred during linking.
      return;
    }
    // The provider was successfully linked.
    // The phone user can now sign in with their phone number or email.
  }];

Điều này cũng có thể được sử dụng để xác thực lại người dùng liên kết email trước khi chạy một thao tác nhạy cảm.

Nhanh

  let credential = EmailAuthProvider.credential(withEmail:email
                                                       link:link)
  Auth.auth().currentUser?.reauthenticate(with: credential) { authData, error in
    if (error) {
      // And error occurred during re-authentication.
      return
    }
    // The user was successfully re-authenticated.
  }

Mục tiêu-C

  FIRAuthCredential *credential =
      [FIREmailAuthCredential credentialWithEmail:email link:link];
  [FIRAuth auth].currentUser
      reauthenticateWithCredential:credential
                        completion:^(FIRAuthDataResult *_Nullable result,
                                     NSError *_Nullable error) {
    if (error) {
      // And error occurred during re-authentication
      return;
    }
    // The user was successfully re-authenticated.
  }];

Tuy nhiên, vì quy trình có thể kết thúc trên một thiết bị khác mà người dùng ban đầu chưa đăng nhập nên quy trình này có thể chưa hoàn tất. Trong trường hợp đó, người dùng có thể gặp lỗi để buộc họ mở liên kết trên cùng một thiết bị. Một số trạng thái có thể được chuyển vào liên kết để cung cấp thông tin về loại hoạt động và uid người dùng.

Nếu bạn tạo dự án vào hoặc sau ngày 15 tháng 9 năm 2023 thì tính năng bảo vệ liệt kê email sẽ được bật theo mặc định. Tính năng này cải thiện tính bảo mật cho tài khoản người dùng trong dự án của bạn, nhưng nó vô hiệu hóa phương thức fetchSignInMethodsForEmail() mà trước đây chúng tôi khuyên bạn nên triển khai các luồng ưu tiên số nhận dạng.

Mặc dù bạn có thể tắt tính năng bảo vệ liệt kê email cho dự án của mình nhưng chúng tôi khuyên bạn không nên làm như vậy.

Xem tài liệu về bảo vệ liệt kê email để biết thêm chi tiết.

Bước tiếp theo

Sau khi người dùng đăng nhập lần đầu tiên, một tài khoản người dùng mới sẽ được tạo và liên kết với thông tin xác thực—tức là tên người dùng và mật khẩu, số điện thoại hoặc thông tin nhà cung cấp dịch vụ xác thực—mà người dùng đã đăng nhập. Tài khoản mới này được lưu trữ như một phần của dự án Firebase của bạn và có thể được sử dụng để xác định người dùng trên mọi ứng dụng trong dự án của bạn, bất kể người dùng đăng nhập bằng cách nào.

  • Trong ứng dụng của mình, bạn có thể lấy thông tin hồ sơ cơ bản của người dùng từ đối tượng User . Xem Quản lý người dùng .

  • Trong Quy tắc bảo mật cơ sở dữ liệu thời gian thực và lưu trữ đám mây của Firebase, bạn có thể lấy ID người dùng duy nhất của người dùng đã đăng nhập từ biến auth và sử dụng nó để kiểm soát dữ liệu nào người dùng có thể truy cập.

Bạn có thể cho phép người dùng đăng nhập vào ứng dụng của mình bằng nhiều nhà cung cấp xác thực bằng cách liên kết thông tin xác thực của nhà cung cấp xác thực với tài khoản người dùng hiện có.

Để đăng xuất một người dùng, hãy gọi signOut: .

Nhanh

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

Mục tiêu-C

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

Bạn cũng có thể muốn thêm mã xử lý lỗi cho đầy đủ các lỗi xác thực. Xem Xử lý lỗi .