Membuat Backup Kode 2FA di PHP

By | 28 October 2025

Dalam sistem keamanan modern, autentikasi dua faktor (2FA) menjadi lapisan penting untuk melindungi akun pengguna dari akses tidak sah. Namun, sering kali pengguna kehilangan akses ke aplikasi autentikasi seperti Google Authenticator atau alamat email yang digunakan untuk OTP. Untuk mencegah terkunci permanen, solusi yang umum diterapkan adalah menyediakan backup kode 2FA.

Backup kode 2FA adalah sekumpulan kode unik yang dapat digunakan sebagai alternatif jika pengguna tidak bisa mengakses faktor autentikasi utama. Biasanya, kode ini diberikan saat pertama kali mengaktifkan 2FA, dan setiap kode hanya bisa digunakan sekali. Artikel ini akan membahas langkah demi langkah cara membuat, menyimpan, dan memverifikasi backup kode 2FA dengan aman menggunakan PHP.

Konsep Backup Kode 2FA

Backup code bekerja seperti OTP statis yang disiapkan di awal. Misalnya, pengguna mendapat 5–10 kode cadangan, dan setiap kali salah satu digunakan, sistem akan menandainya sebagai used di database.

Fitur Keterangan
Jumlah kode 5–10 kode unik per pengguna
Panjang kode 8–10 karakter acak
Format Huruf kapital + angka (mis. 9FD7-KT2P)
Sifat One-time use
Penyimpanan Disimpan dalam bentuk hash (bcrypt) untuk keamanan

Struktur Tabel Database

Kita buat tabel khusus untuk menyimpan kode recovery:

CREATE TABLE user_recovery_codes (
  id INT AUTO_INCREMENT PRIMARY KEY,
  user_id INT NOT NULL,
  code_hash VARCHAR(255) NOT NULL,
  used TINYINT(1) DEFAULT 0,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

Membuat dan Menyimpan Kode Recovery

Berikut contoh script untuk menghasilkan kode acak dan menyimpannya ke database.

<?php
function generateRecoveryCodes($user_id, $jumlah = 5) {
    $codes = [];
    $mysqli = new mysqli("localhost", "root", "", "db_auth");

    for ($i = 0; $i < $jumlah; $i++) {
        // Kode acak dengan 8 karakter (huruf besar + angka)
        $code = strtoupper(substr(str_shuffle('ABCDEFGHJKLMNPQRSTUVWXYZ23456789'), 0, 8));
        $hash = password_hash($code, PASSWORD_DEFAULT);

        $stmt = $mysqli->prepare("INSERT INTO user_recovery_codes (user_id, code_hash) VALUES (?, ?)");
        $stmt->bind_param("is", $user_id, $hash);
        $stmt->execute();

        $codes[] = $code;
    }

    $mysqli->close();
    return $codes;
}

// Contoh penggunaan
$user_id = 1;
$recoveryCodes = generateRecoveryCodes($user_id);

echo "<h3>Backup Kode Anda:</h3><ul>";
foreach ($recoveryCodes as $code) {
    echo "<li>$code</li>";
}
echo "</ul><p>Simpan kode ini dengan aman, jangan bagikan ke siapa pun.</p>";
?>

Tips keamanan:

  • Tampilkan kode hanya sekali setelah dibuat.

  • Jangan simpan versi plaintext di database.

  • Izinkan pengguna untuk mencetak atau mengunduh kode dalam format PDF jika diperlukan.

Verifikasi Backup Code Saat Login

Jika pengguna kehilangan akses ke OTP, mereka bisa memilih “Gunakan kode cadangan” dan memasukkan salah satu kode tersebut.

<?php
function verifyRecoveryCode($user_id, $input_code) {
    $mysqli = new mysqli("localhost", "root", "", "db_auth");

    $stmt = $mysqli->prepare("SELECT id, code_hash, used FROM user_recovery_codes WHERE user_id = ?");
    $stmt->bind_param("i", $user_id);
    $stmt->execute();
    $result = $stmt->get_result();

    while ($row = $result->fetch_assoc()) {
        if (!$row['used'] && password_verify($input_code, $row['code_hash'])) {
            // Tandai sebagai digunakan
            $update = $mysqli->prepare("UPDATE user_recovery_codes SET used = 1 WHERE id = ?");
            $update->bind_param("i", $row['id']);
            $update->execute();

            $mysqli->close();
            return true; // kode valid
        }
    }

    $mysqli->close();
    return false; // tidak cocok
}

// Contoh pemakaian
if (verifyRecoveryCode($user_id, $_POST['backup_code'])) {
    echo "Login berhasil dengan kode cadangan!";
} else {
    echo "Kode tidak valid atau sudah digunakan.";
}
?>

Fitur Tambahan yang Direkomendasikan

Agar sistem backup code lebih profesional dan aman, kamu bisa menambahkan:

  • Regenerasi kode baru: hanya bisa dilakukan setelah login dengan 2FA aktif.

  • Notifikasi email: kirim email setiap kali kode digunakan.

  • Hapus otomatis kode lama: saat pengguna membuat batch kode baru.

Kesimpulan

Dengan menerapkan backup kode 2FA, pengguna memiliki jalan aman untuk memulihkan akses tanpa mengorbankan keamanan akun. Pendekatan ini menjadi standar di berbagai platform besar seperti Google dan GitHub karena melindungi dari kehilangan akses autentikasi utama.

Gunakan metode hashing, one-time use, dan notifikasi email untuk memastikan implementasi sistem cadangan ini tetap kuat dan terpercaya.

Category: PHP