Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

Otentikasi dengan Firebase Menggunakan Tautan Email di JavaScript

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

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

Ada banyak manfaat untuk masuk melalui email:

  • Pendaftaran dan masuk dengan gesekan rendah.
  • Risiko penggunaan kembali kata sandi yang lebih rendah di seluruh aplikasi, yang dapat merusak keamanan kata sandi yang dipilih dengan baik sekalipun.
  • Kemampuan untuk mengautentikasi pengguna sekaligus memverifikasi bahwa pengguna adalah pemilik sah dari alamat email.
  • Pengguna hanya memerlukan akun email yang dapat diakses untuk masuk. Tidak diperlukan kepemilikan nomor telepon atau akun media sosial.
  • Seorang pengguna dapat masuk dengan aman tanpa perlu memberikan (atau mengingat) kata sandi, yang dapat merepotkan pada perangkat seluler.
  • Pengguna yang sudah ada yang sebelumnya masuk dengan pengenal email (kata sandi atau federasi) dapat ditingkatkan untuk masuk hanya dengan email. Misalnya, pengguna yang lupa sandi tetap dapat masuk tanpa perlu menyetel ulang sandi.

Sebelum kamu memulai

Jika Anda belum melakukannya, salin cuplikan inisialisasi dari konsol Firebase ke proyek Anda seperti yang dijelaskan dalam Menambahkan Firebase ke proyek JavaScript Anda .

Untuk membuat pengguna masuk melalui tautan email, Anda harus terlebih dahulu mengaktifkan penyedia Email dan metode masuk tautan Email untuk proyek Firebase Anda:

  1. Di Firebase console , buka bagian Auth .
  2. Pada tab Metode masuk , aktifkan penyedia Email/Kata Sandi . Perhatikan bahwa masuk email/sandi harus diaktifkan untuk menggunakan masuk tautan email.
  3. Di bagian yang sama, aktifkan metode masuk tautan Email (masuk tanpa kata sandi) .
  4. Klik Simpan .

Untuk memulai alur autentikasi, berikan antarmuka kepada pengguna yang meminta pengguna untuk memberikan alamat email mereka, lalu panggil sendSignInLinkToEmail untuk meminta Firebase mengirimkan tautan autentikasi ke email pengguna.

  1. Buat objek ActionCodeSettings , yang memberikan petunjuk kepada Firebase tentang cara membuat tautan email. Setel bidang berikut:

    • url : Tautan dalam untuk disematkan dan status tambahan apa pun yang akan diteruskan. Domain tautan harus ditambahkan dalam daftar domain resmi Firebase Console, yang dapat ditemukan dengan membuka tab Metode masuk (Otentikasi -> Metode masuk).
    • android dan ios : Aplikasi yang digunakan saat tautan masuk dibuka di perangkat Android atau Apple. Pelajari lebih lanjut tentang cara mengonfigurasi Firebase Dynamic Links untuk membuka tautan tindakan email melalui aplikasi seluler.
    • handleCodeInApp : Setel ke true. Operasi masuk harus selalu diselesaikan di aplikasi tidak seperti tindakan email luar lainnya (reset kata sandi dan verifikasi email). Ini karena, di akhir alur, pengguna diharapkan masuk dan status Auth mereka tetap ada di dalam aplikasi.
    • dynamicLinkDomain : Ketika beberapa domain tautan dinamis khusus ditentukan untuk suatu proyek, tentukan yang mana yang akan digunakan ketika tautan akan dibuka melalui aplikasi seluler tertentu (misalnya, example.page.link ). Jika tidak, domain pertama akan dipilih secara otomatis.

      Web version 9

      const actionCodeSettings = {
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be in the authorized domains list in the Firebase Console.
        url: 'https://www.example.com/finishSignUp?cartId=1234',
        // This must be true.
        handleCodeInApp: true,
        iOS: {
          bundleId: 'com.example.ios'
        },
        android: {
          packageName: 'com.example.android',
          installApp: true,
          minimumVersion: '12'
        },
        dynamicLinkDomain: 'example.page.link'
      };

      Web version 8

      var actionCodeSettings = {
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be in the authorized domains list in the Firebase Console.
        url: 'https://www.example.com/finishSignUp?cartId=1234',
        // This must be true.
        handleCodeInApp: true,
        iOS: {
          bundleId: 'com.example.ios'
        },
        android: {
          packageName: 'com.example.android',
          installApp: true,
          minimumVersion: '12'
        },
        dynamicLinkDomain: 'example.page.link'
      };

    Untuk mempelajari lebih lanjut tentang ActionCodeSettings, lihat bagian Passing State di bagian Email Actions .

  2. Mintalah email kepada pengguna.

  3. Kirim tautan autentikasi ke email pengguna, dan simpan email pengguna jika pengguna menyelesaikan proses masuk email di perangkat yang sama.

    Web version 9

    import { getAuth, sendSignInLinkToEmail } from "firebase/auth";
    
    const auth = getAuth();
    sendSignInLinkToEmail(auth, email, actionCodeSettings)
      .then(() => {
        // 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.
        window.localStorage.setItem('emailForSignIn', email);
        // ...
      })
      .catch((error) => {
        const errorCode = error.code;
        const errorMessage = error.message;
        // ...
      });

    Web version 8

    firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings)
      .then(() => {
        // 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.
        window.localStorage.setItem('emailForSignIn', email);
        // ...
      })
      .catch((error) => {
        var errorCode = error.code;
        var errorMessage = error.message;
        // ...
      });

Perhatian pada keamanan

Untuk mencegah tautan masuk digunakan untuk masuk sebagai pengguna yang tidak diinginkan atau pada perangkat yang tidak diinginkan, Firebase Auth mengharuskan alamat email pengguna diberikan saat menyelesaikan alur masuk. Agar proses masuk berhasil, alamat email ini harus cocok dengan alamat tujuan awal pengiriman tautan masuk.

Anda dapat menyederhanakan alur ini untuk pengguna yang membuka tautan masuk di perangkat yang sama yang mereka minta tautannya, dengan menyimpan alamat email mereka secara lokal - misalnya menggunakan penyimpanan lokal atau cookie - saat Anda mengirim email masuk. Kemudian, gunakan alamat ini untuk menyelesaikan alur. Jangan meneruskan email pengguna di parameter URL pengalihan dan gunakan kembali karena ini dapat mengaktifkan injeksi sesi.

Setelah proses masuk selesai, semua mekanisme masuk yang belum diverifikasi sebelumnya akan dihapus dari pengguna dan sesi apa pun yang ada akan menjadi tidak valid. Misalnya, jika seseorang sebelumnya membuat akun yang belum diverifikasi dengan email dan sandi yang sama, sandi pengguna akan dihapus untuk mencegah peniru yang mengklaim kepemilikan dan membuat akun yang belum diverifikasi itu masuk lagi dengan email dan sandi yang belum diverifikasi.

Pastikan juga Anda menggunakan URL HTTPS dalam produksi untuk menghindari tautan Anda berpotensi dicegat oleh server perantara.

Menyelesaikan proses masuk di halaman web

Format tautan dalam tautan email sama dengan format yang digunakan untuk tindakan email luar band (verifikasi email, reset kata sandi, dan pencabutan perubahan email). Firebase Auth menyederhanakan pemeriksaan ini dengan menyediakan isSignInWithEmailLink API untuk memeriksa apakah tautan adalah tautan masuk dengan email.

Untuk menyelesaikan proses masuk di laman landas, hubungi signInWithEmailLink dengan email pengguna dan tautan email sebenarnya yang berisi kode satu kali.

Web version 9

import { getAuth, isSignInWithEmailLink, signInWithEmailLink } from "firebase/auth";

// Confirm the link is a sign-in with email link.
const auth = getAuth();
if (isSignInWithEmailLink(auth, window.location.href)) {
  // Additional state parameters can also be passed via URL.
  // This can be used to continue the user's intended action before triggering
  // the sign-in operation.
  // Get the email if available. This should be available if the user completes
  // the flow on the same device where they started it.
  let email = window.localStorage.getItem('emailForSignIn');
  if (!email) {
    // User opened the link on a different device. To prevent session fixation
    // attacks, ask the user to provide the associated email again. For example:
    email = window.prompt('Please provide your email for confirmation');
  }
  // The client SDK will parse the code from the link for you.
  signInWithEmailLink(auth, email, window.location.href)
    .then((result) => {
      // Clear email from storage.
      window.localStorage.removeItem('emailForSignIn');
      // You can access the new user via result.user
      // Additional user info profile not available via:
      // result.additionalUserInfo.profile == null
      // You can check if the user is new or existing:
      // result.additionalUserInfo.isNewUser
    })
    .catch((error) => {
      // Some error occurred, you can inspect the code: error.code
      // Common errors could be invalid email and invalid or expired OTPs.
    });
}

Web version 8

// Confirm the link is a sign-in with email link.
if (firebase.auth().isSignInWithEmailLink(window.location.href)) {
  // Additional state parameters can also be passed via URL.
  // This can be used to continue the user's intended action before triggering
  // the sign-in operation.
  // Get the email if available. This should be available if the user completes
  // the flow on the same device where they started it.
  var email = window.localStorage.getItem('emailForSignIn');
  if (!email) {
    // User opened the link on a different device. To prevent session fixation
    // attacks, ask the user to provide the associated email again. For example:
    email = window.prompt('Please provide your email for confirmation');
  }
  // The client SDK will parse the code from the link for you.
  firebase.auth().signInWithEmailLink(email, window.location.href)
    .then((result) => {
      // Clear email from storage.
      window.localStorage.removeItem('emailForSignIn');
      // You can access the new user via result.user
      // Additional user info profile not available via:
      // result.additionalUserInfo.profile == null
      // You can check if the user is new or existing:
      // result.additionalUserInfo.isNewUser
    })
    .catch((error) => {
      // Some error occurred, you can inspect the code: error.code
      // Common errors could be invalid email and invalid or expired OTPs.
    });
}

Menyelesaikan proses masuk di aplikasi seluler

Firebase Authentication menggunakan Firebase Dynamic Links untuk mengirim link email ke perangkat seluler. Untuk penyelesaian masuk melalui aplikasi seluler, aplikasi harus dikonfigurasi untuk mendeteksi tautan aplikasi yang masuk, mengurai tautan dalam yang mendasarinya, lalu menyelesaikan proses masuk seperti yang dilakukan melalui alur web.

Untuk mempelajari lebih lanjut tentang cara menangani masuk dengan tautan email di aplikasi Android, lihat panduan Android .

Untuk mempelajari lebih lanjut tentang cara menangani tautan masuk dengan email di aplikasi Apple, lihat panduan platform Apple .

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 masuk ini ke akun mereka yang sudah ada.

Perbedaannya adalah pada paruh kedua operasi:

Web version 9

import { getAuth, linkWithCredential, EmailAuthProvider } from "firebase/auth";

// Construct the email link credential from the current URL.
const credential = EmailAuthProvider.credentialWithLink(
  email, window.location.href);

// Link the credential to the current user.
const auth = getAuth();
linkWithCredential(auth.currentUser, credential)
  .then((usercred) => {
    // The provider is now successfully linked.
    // The phone user can now sign in with their phone number or email.
  })
  .catch((error) => {
    // Some error occurred.
  });

Web version 8

// Construct the email link credential from the current URL.
var credential = firebase.auth.EmailAuthProvider.credentialWithLink(
  email, window.location.href);

// Link the credential to the current user.
firebase.auth().currentUser.linkWithCredential(credential)
  .then((usercred) => {
    // The provider is now successfully linked.
    // The phone user can now sign in with their phone number or email.
  })
  .catch((error) => {
    // Some error occurred.
  });

Ini juga dapat digunakan untuk mengautentikasi ulang pengguna tautan email sebelum menjalankan operasi sensitif.

Web version 9

import { getAuth, reauthenticateWithCredential, EmailAuthProvider } from "firebase/auth";

// Construct the email link credential from the current URL.
const credential = EmailAuthProvider.credentialWithLink(
  email, window.location.href);

// Re-authenticate the user with this credential.
const auth = getAuth();
reauthenticateWithCredential(auth.currentUser, credential)
  .then((usercred) => {
    // The user is now successfully re-authenticated and can execute sensitive
    // operations.
  })
  .catch((error) => {
    // Some error occurred.
  });

Web version 8

// Construct the email link credential from the current URL.
var credential = firebase.auth.EmailAuthProvider.credentialWithLink(
  email, window.location.href);

// Re-authenticate the user with this credential.
firebase.auth().currentUser.reauthenticateWithCredential(credential)
  .then((usercred) => {
    // The user is now successfully re-authenticated and can execute sensitive
    // operations.
  })
  .catch((error) => {
    // Some error occurred.
  });

Namun, karena alur dapat berakhir di perangkat lain tempat pengguna asli tidak masuk, alur ini mungkin tidak selesai. Dalam hal ini, kesalahan dapat ditunjukkan kepada pengguna untuk memaksa mereka membuka tautan di perangkat yang sama. Beberapa status dapat diteruskan di tautan untuk memberikan informasi tentang jenis operasi dan uid pengguna.

Jika Anda mendukung login berbasis sandi dan link dengan email, untuk membedakan metode login untuk pengguna sandi/tautan, gunakan fetchSignInMethodsForEmail . Ini berguna untuk alur pengidentifikasi-pertama di mana pengguna pertama kali diminta untuk memberikan email mereka dan kemudian disajikan dengan metode masuk:

Web version 9

import { getAuth, fetchSignInMethodsForEmail, EmailAuthProvider} from "firebase/auth";

// After asking the user for their email.
const email = window.prompt('Please provide your email');

const auth = getAuth();
fetchSignInMethodsForEmail(auth, email)
  .then((signInMethods) => {
    // This returns the same array as fetchProvidersForEmail but for email
    // provider identified by 'password' string, signInMethods would contain 2
    // different strings:
    // 'emailLink' if the user previously signed in with an email/link
    // 'password' if the user has a password.
    // A user could have both.
    if (signInMethods.indexOf(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/password.
    }
    if (signInMethods.indexOf(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/link.
    }
  })
  .catch((error) => {
    // Some error occurred, you can inspect the code: error.code
  });

Web version 8

// After asking the user for their email.
var email = window.prompt('Please provide your email');
firebase.auth().fetchSignInMethodsForEmail(email)
  .then((signInMethods) => {
    // This returns the same array as fetchProvidersForEmail but for email
    // provider identified by 'password' string, signInMethods would contain 2
    // different strings:
    // 'emailLink' if the user previously signed in with an email/link
    // 'password' if the user has a password.
    // A user could have both.
    if (signInMethods.indexOf(
            firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/password.
    }
    if (signInMethods.indexOf(
            firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/link.
    }
  })
  .catch((error) => {
    // Some error occurred, you can inspect the code: error.code
  });

Seperti dijelaskan di atas, email/sandi dan email/tautan dianggap sebagai firebase.auth.EmailAuthProvider ( PROVIDER_ID ) yang sama dengan metode masuk yang berbeda.

Langkah selanjutnya

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

  • Di aplikasi Anda, cara yang disarankan untuk mengetahui status autentikasi pengguna Anda adalah dengan menyetel pengamat pada objek Auth . Anda kemudian bisa mendapatkan informasi profil dasar pengguna dari objek User . Lihat Kelola Pengguna .

  • Dalam Aturan Keamanan Firebase Realtime Database dan Cloud Storage , Anda bisa mendapatkan ID pengguna unik pengguna yang masuk dari variabel auth , dan menggunakannya untuk mengontrol data apa yang dapat diakses pengguna.

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

Untuk mengeluarkan pengguna, panggil signOut :

Web version 9

import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});

Web version 8

firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});