Konsep dan Cara Kerja TOTP (Time-based One-Time Password) Authenticator
Konsep dan Cara Kerja TOTP (Time-based One-Time Password) Authenticator
TOTP (Time-based One-Time Password) adalah metode autentikasi dua faktor (2FA) yang digunakan untuk meningkatkan keamanan dengan menghasilkan kode sementara yang berbasis waktu. Kode ini biasanya terdiri dari 6-8 digit dan hanya valid untuk waktu tertentu (biasanya 30 detik). TOTP banyak digunakan oleh aplikasi autentikator seperti Google Authenticator, Microsoft Authenticator, dan Authy. Berikut adalah penjelasan lengkap tentang konsep, cara kerja di belakang layar, serta aspek teknis dan keamanan TOTP.
1. Konsep Dasar TOTP
TOTP adalah bagian dari standar HOTP (HMAC-based One-Time Password) yang dimodifikasi untuk menggunakan waktu sebagai faktor dinamis, bukan counter seperti pada HOTP. TOTP dirancang untuk memberikan lapisan keamanan tambahan dengan memastikan bahwa pengguna harus memiliki:
Sesuatu yang mereka ketahui (misalnya, kata sandi).
Sesuatu yang mereka miliki (perangkat dengan aplikasi autentikator yang menghasilkan kode TOTP).
Standar: TOTP diatur oleh RFC 6238 (dari Internet Engineering Task Force, IETF), yang mendefinisikan algoritma untuk menghasilkan kode satu kali berdasarkan waktu menggunakan HMAC (Hash-based Message Authentication Code).
Fitur Utama:
Kode Sementara: Kode berubah setiap 30 detik (atau periode lain yang ditentukan).
Berbasis Waktu: Menggunakan waktu sistem yang tersinkronisasi antara server dan perangkat klien.
Kunci Rahasia Bersama: Server dan perangkat klien berbagi kunci rahasia (secret key) yang digunakan untuk menghasilkan kode yang sama.
Portabilitas: Dapat diimplementasikan di berbagai platform, termasuk aplikasi autentikator di ponsel atau perangkat keras seperti token fisik.
2. Cara Kerja TOTP di Belakang Layar
TOTP bekerja dengan menggabungkan kunci rahasia (shared secret) dan waktu saat ini untuk menghasilkan kode satu kali. Berikut adalah langkah-langkah teknisnya:
a. Komponen Utama
Kunci Rahasia (Secret Key):
Kunci rahasia adalah string acak (biasanya dalam format base32) yang dibagikan antara server dan perangkat klien saat pengaturan 2FA.
Contoh:
XRSCYV6ZK3QAOSOGFHGFPJMVY4AE6MGN
.Kunci ini harus disimpan dengan aman di server (misalnya, di database) dan di perangkat klien (melalui aplikasi autentikator).
Waktu Saat Ini:
TOTP menggunakan waktu saat ini dalam format Unix timestamp (jumlah detik sejak 1 Januari 1970, UTC).
Waktu dibagi menjadi periode waktu tetap (default 30 detik), disebut time step.
Rumus:
T = floor(currentUnixTime / timeStep)
.
Algoritma HMAC-SHA1:
TOTP menggunakan algoritma HMAC-SHA1 untuk menggabungkan kunci rahasia dan waktu saat ini.
HMAC (Hash-based Message Authentication Code) menghasilkan hash yang aman dari input waktu dan kunci rahasia.
Panjang Kode:
Kode biasanya 6 atau 8 digit, dihasilkan dari hash HMAC dengan memotong dan mengonversi sebagian hasil hash ke format numerik.
b. Langkah-Langkah Generasi Kode TOTP
Berikut adalah proses teknis untuk menghasilkan kode TOTP:
Ambil Waktu Saat Ini:
Ambil timestamp Unix saat ini (misalnya,
1695826800
detik).Bagi dengan periode waktu (misalnya, 30 detik):
T = floor(1695826800 / 30) = 56527626
.Konversi
T
ke format byte (biasanya big-endian 64-bit integer).
Gabungkan dengan Kunci Rahasia:
Gunakan kunci rahasia (misalnya,
XRSCYV6ZK3QAOSOGFHGFPJMVY4AE6MGN
, yang didekode dari base32 ke byte).Hitung HMAC-SHA1:
hash = HMAC-SHA1(secret, T)
.
Potong Hash untuk Mendapatkan Kode:
Ambil 4 byte terakhir dari hash HMAC berdasarkan offset dinamis (dynamic truncation).
Konversi 4 byte tersebut ke integer 31-bit (dengan masking bit paling signifikan).
Ambil modulo 10^n (di mana n adalah jumlah digit, misalnya 6 untuk kode 6 digit):
code = integer % 1000000
.Format kode dengan padding nol jika perlu (misalnya,
1234
menjadi001234
).
Validasi di Server:
Server melakukan proses yang sama dengan kunci rahasia yang sama dan waktu saat ini.
Jika kode dari klien cocok dengan kode yang dihasilkan server, autentikasi berhasil.
Untuk menangani sedikit perbedaan waktu (skew), server biasanya memeriksa kode untuk time step saat ini (
T
), satu langkah sebelumnya (T-1
), dan satu langkah berikutnya (T+1
).
c. Proses Pengaturan TOTP
Generasi Kunci Rahasia:
Server menghasilkan kunci rahasia acak menggunakan library seperti
github.com/pquerna/otp
.Kunci ini disimpan di database untuk pengguna terkait.
Pembuatan URL OTPAuth:
Server membuat URL dalam format:
otpauth://totp/[Issuer]:[AccountName]?secret=[Secret]&issuer=[Issuer]&algorithm=SHA1&digits=6&period=30
.Contoh:
otpauth://totp/Notes-API:sammidev4@gmail.com?secret=XRSCYV6ZK3QAOSOGFHGFPJMVY4AE6MGN&issuer=Notes-API
.
Generasi QR Code:
URL di-encode ke dalam QR code menggunakan library seperti
github.com/skip2/go-qrcode
.Pengguna memindai QR code menggunakan aplikasi autentikator, yang menyimpan kunci rahasia dan mulai menghasilkan kode.
Verifikasi Awal:
Pengguna memasukkan kode TOTP pertama untuk memverifikasi bahwa pengaturan berhasil.
Server memvalidasi kode menggunakan algoritma TOTP dan mengaktifkan 2FA jika valid.
d. Proses Autentikasi
Login Awal:
Pengguna memasukkan email dan kata sandi.
Jika 2FA diaktifkan, server mengembalikan respons yang menunjukkan bahwa kode TOTP diperlukan.
Verifikasi TOTP:
Pengguna membuka aplikasi autentikator, yang menampilkan kode 6 digit saat ini.
Pengguna memasukkan kode ke aplikasi.
Server memverifikasi kode dengan menghitung TOTP menggunakan kunci rahasia dan waktu saat ini.
Hasil:
Jika kode valid, server menghasilkan token akses (misalnya, JWT) untuk autentikasi.
Jika kode tidak valid, autentikasi ditolak.
3. Komponen Teknis
Berikut adalah elemen teknis utama dalam implementasi TOTP:
Kunci Rahasia:
Disimpan dalam format base32 untuk portabilitas (mudah dibaca dan dimasukkan secara manual jika diperlukan).
Harus dienkripsi saat disimpan di database untuk keamanan.
Sinkronisasi Waktu:
TOTP bergantung pada sinkronisasi waktu antara server dan perangkat klien.
Perbedaan waktu kecil (time skew) ditangani dengan memvalidasi kode untuk beberapa time step (misalnya, ±30 detik).
Algoritma HMAC-SHA1:
HMAC-SHA1 adalah algoritma default karena keseimbangan antara keamanan dan performa.
Alternatif seperti SHA256 atau SHA512 dapat digunakan, tetapi tidak semua aplikasi autentikator mendukungnya.
Periode Waktu:
Default adalah 30 detik, yang berarti kode baru dihasilkan setiap 30 detik.
Periode dapat disesuaikan, tetapi 30 detik adalah standar industri.
Panjang Kode:
Kode 6 digit adalah standar, memberikan 1 juta kemungkinan kode (10^6).
Kode 8 digit dapat digunakan untuk keamanan lebih tinggi, tetapi kurang umum.
4. Implementasi dalam Kode (Contoh di Go)
Berikut adalah bagaimana TOTP diimplementasikan dalam kode yang Anda gunakan (mengacu pada github.com/pquerna/otp
):
a. Generasi Kunci Rahasia dan QR Code
import (
"github.com/pquerna/otp/totp"
"github.com/skip2/go-qrcode"
"net/url"
)
func (s *userService) Setup2FA(ctx context.Context, req *dto.Setup2FARequest) (*dto.Setup2FAResponse, error) {
// ... kode lain untuk validasi dan pengambilan pengguna ...
// Generate TOTP secret
key, err := totp.Generate(totp.GenerateOpts{
Issuer: "Notes-API",
AccountName: user.Email,
SecretSize: 20,
Digits: otp.DigitsSix,
Algorithm: otp.AlgorithmSHA1,
Period: 30,
})
if err != nil {
return nil, err
}
// Simpan secret ke database
user.TwoFactorSecret = key.Secret()
user.TwoFactorEnabled = false
if err := s.userRepo.Update(ctx, user); err != nil {
return nil, err
}
// Generate URL OTPAuth
issuer := url.QueryEscape("Notes-API")
accountName := url.QueryEscape(user.Email)
otpAuthURL := fmt.Sprintf("otpauth://totp/%s:%s?secret=%s&issuer=%s&algorithm=SHA1&digits=6&period=30",
issuer, accountName, key.Secret(), issuer)
// Generate QR code
qrCodeData, err := qrcode.Encode(otpAuthURL, qrcode.Medium, 256)
if err != nil {
return nil, err
}
qrCodeBase64 := fmt.Sprintf("data:image/png;base64,%s", base64.StdEncoding.EncodeToString(qrCodeData))
return &dto.Setup2FAResponse{
Secret: key.Secret(),
QRCode: qrCodeBase64,
}, nil
}
b. Verifikasi Kode TOTP
func (s *userService) Verify2FA(ctx context.Context, req *dto.Verify2FARequest) (*dto.Verify2FAResponse, error) {
// ... kode lain untuk validasi dan pengambilan pengguna ...
// Verifikasi kode TOTP
valid := totp.Validate(req.Code, user.TwoFactorSecret)
if !valid {
return nil, appErrors.NewAppError(appErrors.ErrCodeInvalidInput, "Invalid 2FA code")
}
// Aktifkan 2FA jika belum aktif
if !user.TwoFactorEnabled {
user.TwoFactorEnabled = true
if err := s.userRepo.Update(ctx, user); err != nil {
return nil, err
}
}
// Generate token JWT
accessToken, err := s.tokenMaker.GenerateToken(user.ID, s.cfg.AuthAccessTokenExpiry)
if err != nil {
return nil, err
}
refreshToken, err := s.tokenMaker.GenerateToken(user.ID, s.cfg.AuthRefreshTokenExpiry)
if err != nil {
return nil, err
}
return &dto.Verify2FAResponse{
Verified: true,
AccessToken: accessToken.Value,
RefreshToken: refreshToken.Value,
AccessTokenExpiresAt: accessToken.ExpiresAt,
RefreshTokenExpiresAt: refreshToken.ExpiresAt,
}, nil
}
5. Keamanan TOTP
TOTP memiliki beberapa keunggulan dan pertimbangan keamanan:
Keunggulan:
Kode Sementara: Karena kode berubah setiap 30 detik, kode yang dicuri tidak dapat digunakan kembali setelah periode tersebut.
Tidak Bergantung pada Jaringan: TOTP bekerja offline, karena kode dihasilkan di perangkat klien berdasarkan waktu dan kunci rahasia.
Standar Terbuka: Didukung oleh banyak aplikasi autentikator dan mudah diimplementasikan.
Pertimbangan Keamanan:
Kebocoran Kunci Rahasia:
Jika kunci rahasia dicuri (misalnya, dari database atau saat pengaturan), penyerang dapat menghasilkan kode TOTP.
Solusi: Enkripsi kunci rahasia di database dan gunakan saluran aman (HTTPS) untuk mengirim QR code.
Sinkronisasi Waktu:
Jika waktu perangkat klien dan server tidak sinkron, kode mungkin tidak valid.
Solusi: Gunakan server waktu (NTP) untuk server dan pastikan perangkat klien tersinkronisasi.
Serangan Man-in-the-Middle (MITM):
Penyerang dapat mencegat kode TOTP jika komunikasi tidak dienkripsi.
Solusi: Gunakan HTTPS dan autentikasi awal (misalnya, JWT) untuk endpoint TOTP.
Phishing:
Pengguna dapat tertipu untuk memasukkan kode TOTP di situs palsu.
Solusi: Edukasi pengguna dan gunakan domain tepercaya.
Kehilangan Perangkat:
Jika perangkat dengan aplikasi autentikator hilang, pengguna tidak dapat login tanpa mekanisme pemulihan.
Solusi: Sediakan kode pemulihan (recovery codes) saat pengaturan 2FA.
6. Best Practices untuk Implementasi TOTP
Simpan Kunci Rahasia dengan Aman:
Enkripsi kunci rahasia di database menggunakan algoritma seperti AES.
Jangan simpan kunci dalam log atau tampilkan di respons kecuali saat pengaturan.
Gunakan QR Code untuk Pengaturan:
QR code memudahkan pengguna untuk mengatur 2FA tanpa memasukkan kunci secara manual.
Pastikan QR code dikirim melalui saluran aman.
Sediakan Kode Pemulihan:
Hasilkan kode pemulihan (misalnya, 10 kode acak) saat pengaturan 2FA dan simpan dengan aman.
Pengguna dapat menggunakan kode ini jika kehilangan akses ke aplikasi autentikator.
Rate Limiting:
Terapkan rate limiting pada endpoint verifikasi TOTP untuk mencegah serangan brute force.
Contoh: Batas 5 percobaan per menit per pengguna.
Sinkronisasi Waktu:
Gunakan server NTP untuk memastikan waktu server akurat.
Validasi kode untuk ±1 time step untuk menangani time skew.
UI/UX yang Jelas:
Berikan panduan pengguna untuk memindai QR code dan menyimpan kode pemulihan.
Tampilkan pesan kesalahan yang jelas jika kode TOTP tidak valid.
7. Contoh Alur Penggunaan
Pengaturan 2FA:
Pengguna login dan mengakses endpoint
/setup-2fa
.Server menghasilkan kunci rahasia dan URL OTPAuth, lalu mengembalikan QR code.
Pengguna memindai QR code dengan Google Authenticator, yang mulai menampilkan kode 6 digit setiap 30 detik.
Pengguna memasukkan kode pertama ke endpoint
/verify-2fa
untuk mengaktifkan 2FA.
Login dengan 2FA:
Pengguna memasukkan email dan kata sandi di endpoint
/login
.Jika 2FA diaktifkan, server mengembalikan respons yang meminta kode TOTP.
Pengguna memasukkan kode dari aplikasi autentikator ke endpoint
/verify-2fa
.Server memverifikasi kode dan mengembalikan token JWT.
Pemulihan:
Jika pengguna kehilangan akses ke aplikasi autentikator, mereka dapat menggunakan kode pemulihan untuk menonaktifkan 2FA atau login.
8. Contoh Implementasi Kode Pemulihan
Untuk menambahkan kode pemulihan, Anda dapat memperbarui Setup2FA
untuk menghasilkan beberapa kode acak dan menyimpannya di database.
Tambahan di entity.User
:
type User struct {
// ... kolom lain ...
TwoFactorSecret string `db:"two_factor_secret"`
TwoFactorEnabled bool `db:"two_factor_enabled"`
TwoFactorRecoveryCodes []string `db:"two_factor_recovery_codes"` // Array kode pemulihan
}
Perbarui Setup2FA
:
func (s *userService) Setup2FA(ctx context.Context, req *dto.Setup2FARequest) (*dto.Setup2FAResponse, error) {
// ... kode lain untuk validasi dan pengambilan pengguna ...
// Generate TOTP secret
key, err := totp.Generate(totp.GenerateOpts{
Issuer: "Notes-API",
AccountName: user.Email,
SecretSize: 20,
Digits: otp.DigitsSix,
Algorithm: otp.AlgorithmSHA1,
Period: 30,
})
if err != nil {
return nil, appErrors.NewAppError(appErrors.ErrCodeInternalError, "Failed to generate 2FA secret")
}
// Generate kode pemulihan
recoveryCodes := make([]string, 10)
for i := 0; i < 10; i++ {
code, err := helper.GenerateOTP(12)
if err != nil {
return nil, appErrors.NewAppError(appErrors.ErrCodeInternalError, "Failed to generate recovery code")
}
recoveryCodes[i] = code
}
user.TwoFactorSecret = key.Secret()
user.TwoFactorEnabled = false
user.TwoFactorRecoveryCodes = recoveryCodes
user.UpdatedAt = time.Now()
if err := s.userRepo.Update(ctx, user); err != nil {
return nil, err
}
// Generate URL OTPAuth
issuer := url.QueryEscape("Notes-API")
accountName := url.QueryEscape(user.Email)
otpAuthURL := fmt.Sprintf("otpauth://totp/%s:%s?secret=%s&issuer=%s&algorithm=SHA1&digits=6&period=30",
issuer, accountName, key.Secret(), issuer)
// Generate QR code
qrCodeData, err := qrcode.Encode(otpAuthURL, qrcode.Medium, 256)
if err != nil {
return nil, appErrors.NewAppError(appErrors.ErrCodeInternalError, "Failed to generate QR code")
}
qrCodeBase64 := fmt.Sprintf("data:image/png;base64,%s", helper.Base64Encode(qrCodeData))
return &dto.Setup2FAResponse{
Secret: key.Secret(),
QRCode: qrCodeBase64,
RecoveryCodes: recoveryCodes,
}, nil
}
Perbarui dto.Setup2FAResponse
:
type Setup2FAResponse struct {
Secret string `json:"secret"`
QRCode string `json:"qr_code"`
RecoveryCodes []string `json:"recovery_codes"`
}
Endpoint untuk Verifikasi Kode Pemulihan:
Tambahkan endpoint /recover-2fa
untuk memverifikasi kode pemulihan dan menonaktifkan 2FA jika diperlukan.
9. Kesimpulan
TOTP adalah metode autentikasi dua faktor yang aman dan andal yang mengandalkan kunci rahasia dan waktu untuk menghasilkan kode sementara. Dengan implementasi yang tepat (seperti menggunakan github.com/pquerna/otp
dan github.com/skip2/go-qrcode
), TOTP dapat diintegrasikan ke dalam aplikasi dengan mudah. Fitur seperti kode pemulihan, rate limiting, dan sinkronisasi waktu penting untuk memastikan keamanan dan pengalaman pengguna yang baik.
Last updated