Menambahkan autentikasi multi-faktor TOTP ke aplikasi web

Jika telah mengupgrade ke Firebase Authentication dengan Identity Platform, Anda dapat menambahkan autentikasi multi-faktor (MFA) sandi sekali pakai (MTP) berbasis waktu ke aplikasi Anda.

Firebase Authentication dengan Identity Platform memungkinkan Anda menggunakan TOTP sebagai faktor tambahan untuk MFA. Jika Anda mengaktifkan fitur ini, pengguna yang mencoba login ke aplikasi Anda akan melihat permintaan TOTP. Untuk membuatnya, mereka harus menggunakan aplikasi pengautentikasi yang mampu menghasilkan kode TOTP yang valid, seperti Google Authenticator.

Sebelum memulai

  1. Aktifkan minimal satu penyedia yang mendukung MFA. Perhatikan bahwa semua penyedia kecuali penyedia berikut mendukung MFA:

    • Autentikasi ponsel
    • Autentikasi anonim
    • Token autentikasi kustom
    • Apple Game Center
  2. Pastikan aplikasi Anda memverifikasi alamat email pengguna. MFA memerlukan verifikasi email. Tindakan ini mencegah pelaku kejahatan mendaftar ke layanan dengan alamat email yang bukan miliknya, lalu mengunci pemilik sebenarnya dari alamat email tersebut dengan menambahkan faktor kedua.

  3. Jika Anda belum melakukannya, instal Firebase JavaScript SDK.

    TOTP MFA hanya didukung di Web SDK modular, versi v9.19.1 dan yang lebih tinggi.

  4. Jika Anda belum melakukannya, instal Firebase Admin SDK.

    TOTP MFA hanya didukung di Firebase Admin SDK versi 11.6.0 dan yang lebih baru.

Mengaktifkan TOTP MFA

Untuk mengaktifkan TOTP sebagai faktor kedua, gunakan Admin SDK atau panggil endpoint REST konfigurasi project.

Untuk menggunakan Admin SDK, jalankan perintah berikut:

import { getAuth } from 'firebase-admin/auth';

getAuth().projectConfigManager().updateProjectConfig(
{
      multiFactorConfig: {
          providerConfigs: [{
              state: "ENABLED",
              totpProviderConfig: {
                  adjacentIntervals: {
                      NUM_ADJ_INTERVALS
                  },
              }
          }]
      }
})

Ganti kode berikut:

  • NUM_ADJ_INTERVALS: Jumlah interval jangka waktu, dari nol hingga sepuluh. Jumlah defaultnya adalah lima.

Untuk mengaktifkan TOTP MFA menggunakan REST API, jalankan perintah berikut:

curl -X PATCH "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=mfa" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: PROJECT_ID" \
    -d \
    '{
        "mfa": {
          "providerConfigs": [{
            "state": "ENABLED",
            "totpProviderConfig": {
              "adjacentIntervals": "NUM_ADJ_INTERVALS"
            }
          }]
       }
    }'

Ganti kode berikut:

  • PROJECT_ID: Project ID.
  • NUM_ADJ_INTERVALS: Jumlah interval jangka waktu, dari nol hingga sepuluh. Jumlah defaultnya adalah lima.

Memilih pola pendaftaran

Anda dapat memilih apakah aplikasi memerlukan autentikasi multi-faktor atau tidak, serta cara dan waktu untuk mendaftarkan pengguna. Beberapa pola yang umum antara lain:

  • Mendaftarkan faktor kedua pengguna sebagai bagian dari pendaftaran. Gunakan metode ini jika aplikasi Anda memerlukan autentikasi multi-faktor untuk semua pengguna.

  • Menawarkan opsi yang dapat dilewati untuk mendaftarkan faktor kedua selama pendaftaran. Jika Anda ingin mendukung, tetapi tidak memerlukan autentikasi multi-faktor di aplikasi, Anda dapat menggunakan pendekatan ini.

  • Memungkinkan untuk menambahkan faktor kedua dari halaman pengelolaan akun atau profil pengguna, bukan dari layar pendaftaran. Hal ini akan meminimalkan hambatan selama proses pendaftaran, sekaligus tetap menyediakan autentikasi multi-faktor untuk pengguna yang rentan terhadap ancaman keamanan.

  • Memerlukan penambahan faktor kedua secara inkremental saat pengguna ingin mengakses fitur dengan persyaratan keamanan yang ditingkatkan.

Mendaftarkan pengguna di TOTP MFA

Setelah Anda mengaktifkan TOTP MFA sebagai faktor kedua untuk aplikasi Anda, terapkan logika sisi klien untuk mendaftarkan pengguna di TOTP MFA:

  1. Impor class dan fungsi MFA yang diperlukan:

    import {
      multiFactor,
      TotpMultiFactorGenerator,
      TotpSecret,
      getAuth,
    } from "firebase/auth";
    
  2. Autentikasi ulang pengguna.

  3. Buat rahasia TOTP untuk pengguna terautentikasi:

    // Generate a TOTP secret.
    const multiFactorSession = await multiFactor(currentUser).getSession();
    const totpSecret = await TotpMultiFactorGenerator.generateSecret(
      multiFactorSession
    );
    
  4. Tampilkan rahasia kepada pengguna dan minta mereka memasukkannya ke dalam aplikasi pengautentikasi mereka.

    Dengan banyak aplikasi pengautentikasi, pengguna dapat dengan cepat menambahkan rahasia TOTP baru dengan memindai kode QR yang merepresentasikan URI kunci yang kompatibel dengan Google Authenticator. Agar dapat membuat kode QR untuk tujuan ini, buat URI dengan generateQrCodeUrl(), lalu enkodekan menggunakan library kode QR pilihan Anda. Contoh:

    const totpUri = totpSecret.generateQrCodeUrl(
        currentUser.email,
        "Your App's Name"
    );
    await QRExampleLib.toCanvas(totpUri, qrElement);
    

    Terlepas dari apakah Anda menampilkan kode QR atau tidak, selalu tampilkan kunci rahasia untuk mendukung aplikasi pengautentikasi yang tidak dapat membaca kode QR:

    // Also display this key:
    const secret = totpSecret.secretKey;
    

    Setelah pengguna menambahkan rahasia ke aplikasi pengautentikasinya, rahasia tersebut akan mulai menghasilkan TOTP.

  5. Minta pengguna mengetik TOTP yang ditampilkan di aplikasi pengautentikasi mereka dan menggunakannya untuk menyelesaikan pendaftaran MFA:

    // Ask the user for a verification code from the authenticator app.
    const verificationCode = // Code from user input.
    
    // Finalize the enrollment.
    const multiFactorAssertion = TotpMultiFactorGenerator.assertionForEnrollment(
      totpSecret,
      verificationCode
    );
    await multiFactor(currentUser).enroll(multiFactorAssertion, mfaDisplayName);
    

Memproses login pengguna dengan faktor kedua

Untuk memproses login pengguna dengan TOTP MFA, gunakan kode berikut:

  1. Impor class dan fungsi MFA yang diperlukan:

    import {
        getAuth,
        getMultiFactorResolver,
        TotpMultiFactorGenerator,
    } from "firebase/auth";
    
  2. Panggil salah satu metode signInWith seperti yang Anda lakukan jika tidak menggunakan MFA. (Misalnya, signInWithEmailAndPassword().) Jika metode ini menampilkan error auth/multi-factor-auth-required, mulai alur MFA aplikasi Anda.

    try {
        const userCredential = await signInWithEmailAndPassword(
            getAuth(),
            email,
            password
        );
        // If the user is not enrolled with a second factor and provided valid
        // credentials, sign-in succeeds.
    
        // (If your app requires MFA, this could be considered an error
        // condition, which you would resolve by forcing the user to enroll a
        // second factor.)
    
        // ...
    } catch (error) {
        switch (error.code) {
            case "auth/multi-factor-auth-required":
                // Initiate your second factor sign-in flow. (See next step.)
                // ...
                break;
            case ...:  // Handle other errors, such as wrong passwords.
                break;
        }
    }
    
  3. Alur MFA aplikasi Anda harus terlebih dahulu meminta pengguna untuk memilih faktor kedua yang ingin mereka gunakan. Anda bisa mendapatkan daftar faktor kedua yang didukung dengan memeriksa properti hints dari instance MultiFactorResolver:

    const mfaResolver = getMultiFactorResolver(getAuth(), error);
    const enrolledFactors = mfaResolver.hints.map(info => info.displayName);
    
  4. Jika pengguna memilih untuk menggunakan TOTP, minta mereka mengetik TOTP yang ditampilkan di aplikasi pengautentikasi mereka dan menggunakannya untuk login:

    switch (mfaResolver.hints[selectedIndex].factorId) {
        case TotpMultiFactorGenerator.FACTOR_ID:
            const otpFromAuthenticator = // OTP typed by the user.
            const multiFactorAssertion =
                TotpMultiFactorGenerator.assertionForSignIn(
                    mfaResolver.hints[selectedIndex].uid,
                    otpFromAuthenticator
                );
            try {
                const userCredential = await mfaResolver.resolveSignIn(
                    multiFactorAssertion
                );
                // Successfully signed in!
            } catch (error) {
                // Invalid or expired OTP.
            }
            break;
        case PhoneMultiFactorGenerator.FACTOR_ID:
            // Handle SMS second factor.
            break;
        default:
            // Unsupported second factor?
            break;
    }
    

Membatalkan pendaftaran dari TOTP MFA

Bagian ini menjelaskan cara menangani pengguna yang membatalkan pendaftaran dari TOTP MFA.

Jika pengguna telah mendaftar untuk beberapa opsi MFA, dan jika mereka membatalkan pendaftaran dari opsi yang terakhir diaktifkan, mereka akan menerima auth/user-token-expired dan logout. Pengguna harus login lagi dan memverifikasi kredensial yang ada—misalnya, alamat email dan sandi.

Untuk membatalkan pendaftaran pengguna, menangani error, dan memicu autentikasi ulang, gunakan kode berikut:

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

try {
    // Unenroll from TOTP MFA.
    await multiFactor(currentUser).unenroll(TotpMultiFactorGenerator.FACTOR_ID);
} catch  (error) {
    if (error.code === 'auth/user-token-expired') {
        // If the user was signed out, re-authenticate them.

        // For example, if they signed in with a password, prompt them to
        // provide it again, then call `reauthenticateWithCredential()` as shown
        // below.

        const credential = EmailAuthProvider.credential(email, password);
        await reauthenticateWithCredential(
            currentUser,
            credential
        );
    }
}

Langkah berikutnya