Buka konsol

Melakukan Autentikasi dengan Firebase Menggunakan Link Email di Android

Anda dapat menggunakan Firebase Authentication untuk membuat pengguna login dengan mengirimkan email yang berisi link, yang dapat mereka klik untuk login. Dalam prosesnya, alamat email pengguna juga akan diverifikasi.

Ada banyak manfaat login dengan email:

  • Proses pendaftaran dan login lebih lancar.
  • Risiko penggunaan ulang sandi pada banyak aplikasi lebih rendah. Penggunaan sandi yang sama dapat mengurangi keamanan, sekalipun sandi sudah dipilih dengan baik.
  • Dapat mengautentikasi pengguna, sekaligus memverifkasi bahwa pengguna adalah pemilik sah alamat email.
  • Pengguna hanya memerlukan akun email yang dapat diakses untuk login. Tidak diperlukan kepemilikan akun media sosial atau nomor telepon.
  • Pengguna dapat login dengan aman tanpa perlu memasukkan (atau mengingat) sandi, yang bisa merepotkan pada perangkat seluler.
  • Pengguna yang sudah ada dan sebelumnya login dengan ID email (sandi atau penyedia identitas gabungan) dapat di-upgrade untuk login dengan email saja. Misalnya, pengguna yang lupa sandi masih dapat login tanpa perlu menyetel ulang sandinya.

Sebelum memulai

Siapkan project Android Anda

  1. Tambahkan Firebase ke project Android jika Anda belum melakukannya.
  2. Pada file build.gradle level project, pastikan untuk menyertakan repositori Maven Google di bagian buildscript dan allprojects Anda.
  3. Tambahkan dependensi untuk library Android Firebase Authentication dan layanan Google Play ke file Gradle modul (tingkat aplikasi) Anda (biasanya app/build.gradle):

    implementation 'com.google.firebase:firebase-auth:17.0.0'
    implementation 'com.google.android.gms:play-services-auth:16.0.1'
    

Untuk membuat pengguna login melalui link email, pertama-tama Anda harus mengaktifkan metode login dengan Link email dan Penyedia email untuk project Firebase Anda:

  1. Di Firebase console, buka bagian Auth.
  2. Pada tab Metode login, aktifkan penyedia Email/Sandi. Perlu diketahui bahwa login dengan email/sandi harus diaktifkan untuk menggunakan metode login dengan link email.
  3. Di bagian yang sama, aktifkan metode login dengan Link email (login tanpa sandi).
  4. Klik Simpan.

Untuk memulai proses autentikasi, tampilkan antarmuka yang akan meminta pengguna memasukkan alamat email, lalu panggil sendSignInLinkToEmail untuk meminta Firebase agar mengirimkan link autentikasi ke email pengguna.

  1. Buat objek ActionCodeSettings yang akan memberi Firebase petunjuk cara membuat link email. Tetapkan kolom berikut:

    • url: Deep link yang akan disematkan dan semua status tambahan yang akan diteruskan. Domain link harus diizinkan dalam daftar Firebase Console domain resmi, yang dapat ditemukan dengan membuka tab Metode login (Authentication -> Metode login). Link tersebut akan mengalihkan pengguna ke URL ini apabila aplikasi tidak terpasang di perangkat pengguna dan aplikasi tidak dapat dipasang.
    • androidPackageName dan IOSBundleId: Aplikasi yang akan digunakan saat link login dibuka di perangkat Android atau iOS. Pelajari lebih lanjut tentang cara mengonfigurasi Firebase Dynamic Links untuk membuka link tindakan email melalui aplikasi seluler.
    • handleCodeInApp: Tetapkan ke true. Operasi login harus selalu diselesaikan di aplikasi, tidak seperti tindakan email out of band yang lain (penyetelan ulang sandi dan verifikasi email). Hal ini karena, di akhir proses, pengguna diharapkan untuk login dan status autentikasinya tetap tersimpan di dalam aplikasi.
    • dynamicLinkDomain: Ketika beberapa domain link dinamis kustom ditetapkan untuk sebuah project, tentukan domain yang akan digunakan jika link akan dibuka melalui aplikasi seluler tertentu (misalnya, example.page.link). Jika tidak, domain pertama akan otomatis dipilih.

    Java
    Android

    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();

    Kotlin
    Android

    val 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()

    Untuk mempelajari lebih lanjut tentang ActionCodeSettings, lihat bagian Meneruskan Status dalam Tindakan Email.

  2. Minta pengguna memberikan alamat emailnya.

  3. Kirim link autentikasi ke email pengguna, dan simpan email tersebut sebagai jaga-jaga jika pengguna menyelesaikan proses login dengan email pada perangkat yang sama.

    Java
    Android

    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.");
                    }
                }
            });

    Kotlin
    Android

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

Masalah keamanan

Guna mencegah link login digunakan untuk login sebagai pengguna yang tidak diinginkan atau pada perangkat yang tidak diinginkan, Firebase Auth mengharuskan pengguna untuk memasukkan alamat emailnya saat menyelesaikan proses login. Agar proses login berhasil, alamat email ini harus sama dengan alamat yang awalnya dikirimi link login.

Anda dapat menyederhanakan proses ini untuk pengguna yang membuka link login di perangkat yang sama dengan yang digunakan untuk meminta link, dengan menyimpan alamat emailnya secara lokal - misalnya menggunakan SharedPreferences - saat Anda mengirimkan email login. Kemudian, gunakan alamat ini untuk menyelesaikan proses. Jangan teruskan dan gunakan kembali alamat email pengguna dalam parameter URL alihan karena tindakan ini dapat mengaktifkan injeksi sesi.

Setelah proses login selesai, semua mekanisme login yang sebelumnya tidak diverifikasi akan dihapus dari pengguna dan semua sesi yang ada menjadi tidak valid. Misalnya, jika seseorang sebelumnya membuat akun yang tidak diverifikasi dengan email dan sandi yang sama, maka sandi pengguna tersebut akan dihapus. Dengan begitu, peniru identitas yang mengklaim kepemilikan dan membuat akun yang tidak diverifikasi tersebut tidak akan dapat login lagi dengan email dan sandi yang tidak diverifikasi.

Selain itu, pastikan Anda menggunakan URL HTTPS agar link tidak dihalangi oleh server perantara.

Menyelesaikan proses login di aplikasi Android

Firebase Authentication menggunakan Firebase Dynamic Links untuk mengirim link email ke perangkat seluler. Untuk menyelesaikan proses login melalui aplikasi seluler, aplikasi harus dikonfigurasi untuk mendeteksi link aplikasi masuk, mengurai deep link yang mendasari, lalu menyelesaikan proses login.

Firebase Auth menggunakan Firebase Dynamic Links saat mengirim link yang dimaksudkan untuk dibuka di aplikasi seluler. Untuk menggunakan fitur ini, Dynamic Links harus dikonfigurasikan di Firebase Console.

  1. Aktifkan Firebase Dynamic Links:

    1. Di Firebase console, buka bagian Dynamic Links.
    2. Jika Anda belum menyetujui persyaratan Dynamic Links dan membuat domain Dynamic Links, lakukan sekarang.

      Jika Anda telah membuat domain Dynamic Links, catat domain tersebut. Domain Dynamic Links biasanya terlihat seperti contoh berikut:

      example.page.link

      Anda akan memerlukan nilai ini saat mengonfigurasi aplikasi iOS atau Android Anda untuk menghalangi link masuk.

  2. Mengonfigurasi aplikasi Android:

    1. Untuk menangani link ini dari aplikasi Android, Anda harus menentukan nama package Android di setelan project Firebase Console. Selain itu, SHA-1 dan SHA-256 sertifikat aplikasi harus dimasukkan.
    2. Setelah Anda menambahkan domain link dinamis dan memastikan bahwa aplikasi Android sudah dikonfigurasikan dengan benar, link dinamis akan dialihkan ke aplikasi Anda, mulai dari aktivitas peluncur.
    3. Agar link dinamis dapat mengarahkan ke aktivitas tertentu, Anda harus mengonfigurasi filter intent di file AndroidManifest.xml Anda. Hal ini dapat dilakukan dengan menentukan domain link dinamis atau pengendali tindakan email dalam filter intent. Secara default, pengendali tindakan email dihosting pada domain seperti contoh berikut:
      PROJECT_ID.firebaseapp.com/
    4. Peringatan:
      1. Jangan tentukan URL yang Anda tetapkan pada actionCodeSettings di filter intent Anda.
      2. Saat membuat domain link dinamis, Anda mungkin juga telah membuat link URL singkat. URL singkat ini tidak akan diteruskan; jangan mengonfigurasi filter intent Anda untuk menangkapnya dengan atribut android:pathPrefix. Artinya, Anda tidak akan dapat menangkap link dinamis yang berbeda di berbagai bagian aplikasi Anda. Namun, Anda dapat memeriksa parameter kueri mode di link tersebut untuk melihat operasi yang berusaha dijalankan, atau menggunakan metode SDK, seperti isSignInWithEmailLink, untuk melihat apakah link yang telah diterima aplikasi melakukan hal yang Anda inginkan atau tidak.
    5. Untuk informasi selengkapnya tentang penerimaan link dinamis, lihat Menerima petunjuk Dynamic Links Android.

Setelah Anda menerima link seperti yang dijelaskan di atas, pastikan bahwa link tersebut dimaksudkan untuk autentikasi link email dan selesaikan proses login.

Java
Android

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());
                    }
                }
            });
}

Kotlin
Android

val auth = FirebaseAuth.getInstance()
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)
                }
            }
}

Untuk mempelajari lebih lanjut tentang cara menangani proses login dengan link email pada aplikasi iOS, lihat Panduan iOS.

Untuk mempelajari tentang cara menangani proses login dengan link email pada aplikasi web, lihat Panduan Web.

Anda juga dapat menautkan metode autentikasi ini ke pengguna yang sudah ada. Misalnya, pengguna yang sebelumnya diautentikasi dengan penyedia lain, seperti nomor telepon, dapat menambahkan metode login ini ke akunnya yang sudah ada.

Perbedaannya terletak pada paruh kedua operasi:

Java
Android

// 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());
                }
            }
        });

Kotlin
Android

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

// Link the credential to the current user.
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)
            }
        }

Metode ini juga dapat digunakan untuk mengautentikasi ulang pengguna link email sebelum menjalankan operasi yang sensitif.

Java
Android

// 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());
                }
            }
        });

Kotlin
Android

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

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

Namun, karena proses ini dapat berakhir di perangkat berbeda yang tidak digunakan pengguna awal untuk login, proses ini mungkin tidak akan diselesaikan. Dalam hal ini, pesan error dapat ditampilkan kepada pengguna yang mengharuskan mereka membuka link di perangkat yang sama. Beberapa status dapat diteruskan di link untuk memberikan informasi tentang jenis operasi dan UID pengguna.

Jika Anda mendukung metode login dengan link email dan juga sandi email, gunakan fetchSignInMethodsForEmail untuk membedakan metode login bagi pengguna sandi/link. Cara ini berguna dalam proses ID-dahulu, yakni ketika pengguna diminta memasukkan emailnya dahulu, baru ditunjukkan metode login:

Java
Android

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());
                }
            }
        });

Kotlin
Android

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)
        }

Seperti yang dijelaskan di atas, email/sandi dan email/link dianggap sebagai EmailAuthProvider yang sama (PROVIDER_ID yang sama) pada metode login yang berbeda.

Langkah berikutnya

Setelah pengguna login untuk pertama kalinya, akun pengguna baru akan dibuat dan dihubungkan ke kredensial, yaitu nama pengguna dan sandi, nomor telepon, atau informasi penyedia autentikasi, yang digunakan pengguna tersebut untuk login. Akun baru ini disimpan sebagai bagian dari project Firebase Anda dan dapat digunakan untuk mengidentifikasi pengguna di setiap aplikasi dalam project Anda, terlepas dari cara pengguna login.

  • Dalam aplikasi, Anda bisa memperoleh informasi profil dasar pengguna dari objek FirebaseUser . Lihat Mengelola Pengguna.

  • Dalam Aturan Keamanan Firebase Realtime Database dan Cloud Storage, Anda dapat memperoleh ID unik milik pengguna yang login dari variabel auth dan menggunakannya untuk mengontrol data yang dapat diakses pengguna.

Anda dapat mengizinkan pengguna untuk login ke aplikasi Anda menggunakan beberapa penyedia autentikasi dengan menautkan kredensial penyedia autentikasi ke akun pengguna yang ada.

Agar pengguna logout, panggil signOut:

Java
Android

FirebaseAuth.getInstance().signOut();

Kotlin
Android

FirebaseAuth.getInstance().signOut()