Catch up on highlights from Firebase at Google I/O 2023. Learn more

Xác thực với Firebase bằng Liên kết email trong Android

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 ma sát thấp.
  • 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ỹ lưỡ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 một 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, mật khẩu có thể rườm rà trên thiết bị di động.
  • Người dùng hiện tại trước đây đã đăng nhập bằng số 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

Thiết lập dự án Android của bạn

  1. Nếu bạn chưa có, hãy thêm Firebase vào dự án Android của bạn .

  2. Trong tệp Gradle mô-đun (cấp ứng dụng) của bạn (thường là <project>/<app-module>/build.gradle ), hãy thêm phần phụ thuộc cho thư viện Android Xác thực Firebase. Chúng tôi khuyên bạn nên sử dụng Firebase Android BoM để kiểm soát việc lập phiên bản thư viện.

    Ngoài ra, trong quá trình thiết lập Xác thực Firebase, bạn cần thêm SDK dịch vụ của Google Play vào ứng dụng của mình.

    Kotlin+KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:32.1.0')
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-auth-ktx'
    // Also add the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:20.5.0'
    }

    Bằng cách sử dụng Firebase Android BoM , ứng dụng của bạn sẽ luôn sử dụng các phiên bản tương thích của thư viện Android Firebase.

    (Thay thế) Thêm phụ thuộc thư viện Firebase mà không cần sử dụng BoM

    Nếu chọn không sử dụng Firebase BoM, bạn phải chỉ định từng phiên bản thư viện Firebase trong dòng phụ thuộc của nó.

    Lưu ý rằng nếu bạn sử dụng nhiều thư viện Firebase trong ứng dụng của mình, chúng tôi thực sự khuyên bạn nên sử dụng BoM để quản lý các phiên bản thư viện, điều này đảm bảo rằng tất cả các phiên bản đều tương thích.

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-auth-ktx:22.0.0'
    // Also add the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:20.5.0'
    }

    Java

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:32.1.0')
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-auth'
    // Also add the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:20.5.0'
    }

    Bằng cách sử dụng Firebase Android BoM , ứng dụng của bạn sẽ luôn sử dụng các phiên bản tương thích của thư viện Android Firebase.

    (Thay thế) Thêm phụ thuộc thư viện Firebase mà không cần sử dụng BoM

    Nếu chọn không sử dụng Firebase BoM, bạn phải chỉ định từng phiên bản thư viện Firebase trong dòng phụ thuộc của nó.

    Lưu ý rằng nếu bạn sử dụng nhiều thư viện Firebase trong ứng dụng của mình, chúng tôi thực sự khuyên bạn nên sử dụng BoM để quản lý các phiên bản thư viện, điều này đảm bảo rằng tất cả các phiên bản đều tương thích.

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-auth:22.0.0'
    // Also add the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:20.5.0'
    }

Để đăng nhập người dùng bằng liên kết email, trước tiên bạn phải bật phương thức đăng nhập nhà cung cấp Email và 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 Auth .
  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 đăng nhập email/mật khẩu phải được bật để sử dụng đăng nhập liên kết email.
  3. Trong cùng một phần, hãy bật phương thức đăng nhập bằng 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 quy trình xác thực, hãy cung cấp 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 sendSignInLinkToEmail để 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 , 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 danh sách này bằng cách chuyển đến tab Phương thức đăng nhập (Xác thực -> Phương thức đăng nhập). Liên kết sẽ chuyển hướng người dùng đến URL này nếu ứng dụng chưa được cài đặt trên thiết bị của họ và không thể cài đặt ứng dụng.
    • androidPackageNameIOSBundleId : 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 tác vụ email thông qua ứng dụng dành cho thiết bị di động.
    • handleCodeInApp : Đặ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 thao tác email khác (đặt lại mật khẩu và xác minh email). Điều này là do, khi kết thúc quy trình, người dùng phải đă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 nhiều miền liên kết động tùy chỉnh được xác đị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ở qua một ứng dụng dành cho thiết bị 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.

    Kotlin+KTX

    val actionCodeSettings = actionCodeSettings {
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be whitelisted in the Firebase Console.
        url = "https://www.example.com/finishSignUp?cartId=1234"
        // This must be true
        handleCodeInApp = true
        setIOSBundleId("com.example.ios")
        setAndroidPackageName(
            "com.example.android",
            true, // installIfNotAvailable
            "12", // minimumVersion
        )
    }

    Java

    ActionCodeSettings actionCodeSettings =
            ActionCodeSettings.newBuilder()
                    // URL you want to redirect back to. The domain (www.example.com) for this
                    // URL must be whitelisted in the Firebase Console.
                    .setUrl("https://www.example.com/finishSignUp?cartId=1234")
                    // This must be true
                    .setHandleCodeInApp(true)
                    .setIOSBundleId("com.example.ios")
                    .setAndroidPackageName(
                            "com.example.android",
                            true, /* installIfNotAvailable */
                            "12"    /* minimumVersion */)
                    .build();

    Để tìm hiểu thêm về ActionCodeSettings, hãy tham khảo phần Passing State trong Email Actions .

  2. Yêu cầu người dùng cho 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ị.

    Kotlin+KTX

    Firebase.auth.sendSignInLinkToEmail(email, actionCodeSettings)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d(TAG, "Email sent.")
            }
        }

    Java

    FirebaseAuth auth = FirebaseAuth.getInstance();
    auth.sendSignInLinkToEmail(email, actionCodeSettings)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Email sent.");
                    }
                }
            });

mối quan tâm an ninh

Để ngăn liên kết đăng nhập được sử dụng để đăng nhập với tư cách là người dùng không mong muốn hoặc trên thiết bị không mong 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 ban đầu được gửi đến.

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 một 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ọ - chẳng hạn như sử dụng SharedPreferences - khi bạn gửi email đăng nhập. Sau đó, sử dụng địa chỉ này để hoàn thành quy trình. Không chuyển email của người dùng trong các tham số URL chuyển hướng và sử dụng lại nó vì điều này có thể kích hoạt tiêm phiên.

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 đó ai đó đã tạo một tài khoản chưa được xác minh bằng cùng một email và mật khẩu, thì mật khẩu của người dùng sẽ bị xóa để ngăn kẻ 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 email và mật khẩu chưa được xác minh.

Ngoài ra, hãy đảm bảo rằng bạn sử dụng URL HTTPS trong quá trình sản xuất để tránh khả năng máy chủ trung gian chặn liên kết của bạn.

Hoàn tất đăng nhập trong Ứng dụng Android

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 dành cho thiết bị 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 cú pháp liên kết sâu bên dưới và sau đó hoàn tất đăng nhập.

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

  1. Bậ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 một miền Liên kết động, hãy làm như vậy ngay bây giờ.

      Nếu bạn đã tạo một miền Liên kết động, hãy lưu ý về 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 các ứng dụng Android:

    1. Để xử lý các liên kết này từ ứng dụng Android của bạn, tên gói Android cần được chỉ định trong cài đặt dự án Bảng điều khiển Firebase. Ngoài ra, cần cung cấp SHA-1 và SHA-256 của chứng chỉ ứng dụng.
    2. Bây giờ bạn đã thêm một miền liên kết động và đảm bảo rằng ứng dụng Android của bạn được định cấu hình chính xác, liên kết động sẽ chuyển hướng đến ứng dụng của bạn, bắt đầu từ hoạt động của trình khởi chạy.
    3. Nếu muốn liên kết động chuyển hướng đến một hoạt động cụ thể, bạn sẽ cần định cấu hình bộ lọc ý định trong tệp AndroidManifest.xml của mình. Điều này có thể được thực hiện bằng cách chỉ định miền liên kết động của bạn hoặc trình xử lý hành động email trong bộ lọc ý định. 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:
      PROJECT_ID.firebaseapp.com/
    4. Hãy cẩn thận:
      1. Không chỉ định URL bạn đã đặt trên ActionCodeSettings trong bộ lọc ý định của mình.
      2. Khi tạo miền liên kết động, bạn cũng có thể đã tạo một liên kết URL ngắn. URL ngắn này sẽ không được thông qua; không định cấu hình bộ lọc ý định của bạn để bắt nó bằng thuộc tính android:pathPrefix . Điều này có nghĩa là bạn sẽ không thể bắt các liên kết động khác nhau trong các phần khác nhau của ứng dụng của mình. Tuy nhiên, bạn có thể kiểm tra tham số truy vấn chế mode trong liên kết để xem thao tác nào đang cố thực hiện hoặc sử dụng các phương thức SDK chẳng hạn như isSignInWithEmailLink để xem liệu liên kết mà ứng dụng của bạn đã nhận có làm những gì bạn muốn hay không.
    5. Để biết thêm về cách nhận liên kết động, hãy tham khảo Hướng dẫn nhận liên kết động Android .

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.

Kotlin+KTX

val auth = Firebase.auth
val intent = intent
val emailLink = intent.data.toString()

// Confirm the link is a sign-in with email link.
if (auth.isSignInWithEmailLink(emailLink)) {
    // Retrieve this from wherever you stored it
    val email = "someemail@domain.com"

    // The client SDK will parse the code from the link for you.
    auth.signInWithEmailLink(email, emailLink)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d(TAG, "Successfully signed in with email link!")
                val result = task.result
                // You can access the new user via result.getUser()
                // Additional user info profile *not* available via:
                // result.getAdditionalUserInfo().getProfile() == null
                // You can check if the user is new or existing:
                // result.getAdditionalUserInfo().isNewUser()
            } else {
                Log.e(TAG, "Error signing in with email link", task.exception)
            }
        }
}

Java

FirebaseAuth auth = FirebaseAuth.getInstance();
Intent intent = getIntent();
String emailLink = intent.getData().toString();

// Confirm the link is a sign-in with email link.
if (auth.isSignInWithEmailLink(emailLink)) {
    // Retrieve this from wherever you stored it
    String email = "someemail@domain.com";

    // The client SDK will parse the code from the link for you.
    auth.signInWithEmailLink(email, emailLink)
            .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Successfully signed in with email link!");
                        AuthResult result = task.getResult();
                        // You can access the new user via result.getUser()
                        // Additional user info profile *not* available via:
                        // result.getAdditionalUserInfo().getProfile() == null
                        // You can check if the user is new or existing:
                        // result.getAdditionalUserInfo().isNewUser()
                    } else {
                        Log.e(TAG, "Error signing in with email link", task.getException());
                    }
                }
            });
}

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

Để tìm hiểu về cách xử lý đă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 một 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ẽ là trong nửa sau của hoạt động:

Kotlin+KTX

// Construct the email link credential from the current URL.
val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink)

// Link the credential to the current user.
Firebase.auth.currentUser!!.linkWithCredential(credential)
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            Log.d(TAG, "Successfully linked emailLink credential!")
            val result = task.result
            // You can access the new user via result.getUser()
            // Additional user info profile *not* available via:
            // result.getAdditionalUserInfo().getProfile() == null
            // You can check if the user is new or existing:
            // result.getAdditionalUserInfo().isNewUser()
        } else {
            Log.e(TAG, "Error linking emailLink credential", task.exception)
        }
    }

Java

// Construct the email link credential from the current URL.
AuthCredential credential =
        EmailAuthProvider.getCredentialWithLink(email, emailLink);

// Link the credential to the current user.
auth.getCurrentUser().linkWithCredential(credential)
        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    Log.d(TAG, "Successfully linked emailLink credential!");
                    AuthResult result = task.getResult();
                    // You can access the new user via result.getUser()
                    // Additional user info profile *not* available via:
                    // result.getAdditionalUserInfo().getProfile() == null
                    // You can check if the user is new or existing:
                    // result.getAdditionalUserInfo().isNewUser()
                } else {
                    Log.e(TAG, "Error linking emailLink credential", task.getException());
                }
            }
        });

Đ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.

Kotlin+KTX

// Construct the email link credential from the current URL.
val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink)

// Re-authenticate the user with this credential.
Firebase.auth.currentUser!!.reauthenticateAndRetrieveData(credential)
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            // User is now successfully reauthenticated
        } else {
            Log.e(TAG, "Error reauthenticating", task.exception)
        }
    }

Java

// Construct the email link credential from the current URL.
AuthCredential credential =
        EmailAuthProvider.getCredentialWithLink(email, emailLink);

// Re-authenticate the user with this credential.
auth.getCurrentUser().reauthenticateAndRetrieveData(credential)
        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    // User is now successfully reauthenticated
                } else {
                    Log.e(TAG, "Error reauthenticating", task.getException());
                }
            }
        });

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ể không hoàn thành. Trong trường hợp đó, một lỗi có thể được hiển thị cho người dùng để 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.

Trong trường hợp bạn hỗ trợ cả mật khẩu và đăng nhập dựa trên liên kết bằng email, để phân biệt phương thức đăng nhập cho người dùng mật khẩu/liên kết, hãy sử dụng fetchSignInMethodsForEmail . Điều này hữu ích cho các luồng ưu tiên định danh trong đó trước tiên người dùng được yêu cầu cung cấp email của họ và sau đó được cung cấp phương thức đăng nhập:

Kotlin+KTX

Firebase.auth.fetchSignInMethodsForEmail(email)
    .addOnSuccessListener { result ->
        val signInMethods = result.signInMethods!!
        if (signInMethods.contains(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD)) {
            // User can sign in with email/password
        } else if (signInMethods.contains(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD)) {
            // User can sign in with email/link
        }
    }
    .addOnFailureListener { exception ->
        Log.e(TAG, "Error getting sign in methods for user", exception)
    }

Java

auth.fetchSignInMethodsForEmail(email)
        .addOnCompleteListener(new OnCompleteListener<SignInMethodQueryResult>() {
            @Override
            public void onComplete(@NonNull Task<SignInMethodQueryResult> task) {
                if (task.isSuccessful()) {
                    SignInMethodQueryResult result = task.getResult();
                    List<String> signInMethods = result.getSignInMethods();
                    if (signInMethods.contains(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD)) {
                        // User can sign in with email/password
                    } else if (signInMethods.contains(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD)) {
                        // User can sign in with email/link
                    }
                } else {
                    Log.e(TAG, "Error getting sign in methods for user", task.getException());
                }
            }
        });

Như đã mô tả ở trên email/mật khẩu và email/liên kết được coi là cùng một EmailAuthProvider (cùng PROVIDER_ID ) với các phương thức đăng nhập khác nhau.

Bước tiếp theo

Sau khi người dùng đăng nhập lần đầu tiên, tài khoản người dùng mới được tạo và liên kết với thông tin đăng nhập—nghĩa 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 xác thực—người dùng đã đăng nhập bằng. 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 các ứ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 FirebaseUser . Xem Quản lý người dùng .

  • Trong Cơ sở dữ liệu thời gian thực Firebase và Quy tắc bảo mật bộ lưu trữ đám mây , 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 biến đó để kiểm soát dữ liệu mà 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 đăng nhập 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 người dùng, hãy gọi signOut :

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();