Pernah khawatir password login ke aplikasi Laravel Anda mudah dibobol? Faktanya, serangan cyber kini semakin pintar dan login dengan kata sandi saja tidak lagi aman. Di sinilah 2FA login di Laravel berperan, menambah lapisan verifikasi sehingga akun terlindungi lebih kuat.
Dalam artikel ini, kami akan berbagi tentang apa itu two-factor authentication login, hingga cara mengaktifkan 2FA login di Laravel agar aplikasi semakin aman dan profesional.
Mengenal Two Factor Authentication Login
Two Factor Authentication (2FA) adalah sistem keamanan tambahan yang mengharuskan user untuk melewati dua tahap verifikasi sebelum berhasil login. Biasanya, tahap pertama adalah memasukkan password, lalu dilanjutkan dengan kode unik yang dikirim melalui aplikasi autentikator, SMS, atau email.
Dengan cara ini, meski password bocor sekalipun, akun tetap sulit diakses tanpa kode verifikasi kedua. Dalam pengembangan aplikasi berbasis PHP, 2FA login di Laravel bisa diintegrasikan dengan mudah menggunakan package atau library tambahan, sehingga keamanan login semakin terjamin tanpa mengurangi kenyamanan pengguna.
Selengkapnya tentang apa itu two-factor authentication login bisa Anda pelajari di artikel berikut.
Mengaktifkan 2FA Login di Laravel
Berikut adalah cara untuk mengaktifkan fitur 2FA login di framework Laravel.
Step 1. Install Breeze Laravel
Penting!
Sebelum memulai, kami sarankan Anda untuk backup file webnya. Panduan ini menggunakan Laravel Framework 10.48.29.
Tahap pertama, pastikan aplikasi Laravel Anda sudah jalan. Selanjutnya, akses folder web melalui terminal dan jalankan perintah berikut:
composer require laravel/breeze --dev
php artisan breeze:installPada php artisan breeze, silahkan pilih blade seperti gambar diatas dan pilihlah PHPUnit untuk pilihan berikutnya. Langkah selanjutnya, jalankan perintah npm berikut:
npm install && npm run devStep 2. Migrate Database Laravel
Proses selanjutnya yaitu melengkapi tabel database yang sudah ada. Jalankan perintah berikut:
php artisan make:migration add_otp_columns_to_users_tableSilahkan update isi file add_otp_columns_to_users_table dalam folder database\migrations dengan script dibawah:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('otp_enabled')->default(false);
$table->string('otp_code')->nullable();
$table->timestamp('otp_expires_at')->nullable();
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
});
}
};Perhatikan bagian “Schema::table(‘users’“, silahkan disesuaikan dengan nama table database Anda jika tidak menggunakan users. Jalankan perintah berikut jika kodenya telah disesuaikan:
php artisan migratejika proses migrate database tidak mengalami kendala, silahkan lanjutkan ke langkah berikutnya.
Step 3. Aktifkan SendOTP Laravel dan View Emails
Langkah berikutnya dengan mengaktifkan sendOTP yang berfungsi sebagai metode pengiriman kode ke emailnya. Jalankan perintah berikut:
php artisan make:mail SendOTPProses berikutnya silahkan Anda masuk ke folder resources\views , buatlah folder baru dengan nama emails dengan isi file bernama otp.blade.php
Berikut isi dari script otp.blade.php yang bisa Anda gunakan:
<div style="font-family: Arial, sans-serif; background-color: #f4f4f4; padding: 30px; color: #333;">
<div style="max-width: 600px; margin: 0 auto; background-color: #ffffff; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); padding: 30px;">
<h1 style="font-size: 24px; color: #4F46E5; text-align: center; margin-bottom: 20px;">Verifikasi Kode OTP Anda</h1>
<p style="font-size: 16px; text-align: center;">Berikut adalah kode OTP yang Anda minta untuk verifikasi:</p>
<div style="text-align: center; margin: 30px 0;">
<span style="display: inline-block; background-color: #4F46E5; color: #ffffff; font-size: 32px; font-weight: bold; padding: 12px 24px; border-radius: 8px; letter-spacing: 4px;">
{{ $otp }}
</span>
</div>
<p style="font-size: 14px; text-align: center; color: #666;">
Kode ini berlaku selama <strong>5 menit</strong>. Jangan berikan kode ini kepada siapa pun.
</p>
<hr style="margin: 30px 0; border: none; border-top: 1px solid #e0e0e0;">
<p style="font-size: 12px; text-align: center; color: #999;">
Jika Anda tidak meminta kode ini, Anda bisa mengabaikan email ini atau menghubungi admin: admin@fredriclesomar.id
</p>
</div>
</div>Tampilan diatas adalah form ketika kode OTP dikirimkan ke email terdaftar.
Step 4. Buat file View Auth
Langkah berikutnya dengan membuat file baru dengan nama otp-verify.blade.php di dalam folder resources\views\auth.
<x-guest-layout>
<div class="min-h-screen flex items-center justify-center bg-gray-100 dark:bg-gray-900">
<div class="w-full max-w-md bg-white dark:bg-gray-800 p-8 rounded-lg shadow-lg space-y-6">
{{-- Header --}}
<div class="text-center">
<div class="mx-auto w-16 h-16 flex items-center justify-center rounded-full bg-indigo-100 dark:bg-indigo-500 text-indigo-600 dark:text-white mb-4">
<svg class="w-8 h-8" fill="none" stroke="currentColor" stroke-width="2"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round"
d="M16 12a4 4 0 01-8 0m8 0a4 4 0 00-8 0m8 0V6a4 4 0 00-8 0v6m8 0l4 4m-4-4l-4 4"/>
</svg>
</div>
<h2 class="text-xl font-semibold text-gray-800 dark:text-white">Verifikasi OTP</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
Periksa email Anda untuk mendapatkan kode OTP.
</p>
</div>
{{-- Alert Jika Link Terkirim --}}
@if (session('status') == 'verification-link-sent')
<div class="p-3 text-sm text-green-700 bg-green-100 rounded dark:bg-green-700 dark:text-green-100">
Tautan verifikasi baru telah dikirim ke email Anda.
</div>
@endif
{{-- Form OTP --}}
<form method="POST" action="{{ route('otp.verify') }}" class="space-y-4">
@csrf
<div>
<label for="otp" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
Masukkan Kode OTP
</label>
<input
type="text"
name="otp"
id="otp"
required
placeholder="Contoh: 123456"
class="mt-1 block w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-gray-900 dark:text-white dark:bg-gray-700 focus:ring-indigo-500 focus:border-indigo-500"
>
</div>
<button
type="submit"
class="w-full inline-flex justify-center items-center px-4 py-2 bg-indigo-600 hover:bg-indigo-700 text-white text-sm font-medium rounded-md shadow focus:outline-none focus:ring-2 focus:ring-indigo-500"
>
Verifikasi
</button>
</form>
{{-- Kirim Ulang --}}
<form method="POST" action="{{ route('verification.send') }}" class="text-center">
@csrf
<button type="submit"
class="text-sm text-indigo-600 hover:text-indigo-800 dark:text-indigo-400 dark:hover:text-indigo-200 hover:underline mt-2">
Kirim Ulang Kode OTP
</button>
</form>
{{-- Logout --}}
<form method="POST" action="{{ route('logout') }}" class="text-center">
@csrf
<button type="submit"
class="text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-white underline">
Log Out
</button>
</form>
</div>
</div>
</x-guest-layout>Step 5. Buat File Mail SendOTP
Langkah berikutnya dengan mengupdate isi file SendOTP.php dalam folder app/Mail/ yang sudah Anda buat di step 3 sebelumnya.
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
use Illuminate\Http\Request;
class SendOTP extends Mailable
{
use Queueable, SerializesModels;
public $otp;
public function __construct($otp) { $this->otp = $otp; }
public function build()
{
return $this->subject('Kode OTP Login')->view('emails.otp');
}
public function envelope(): Envelope
{
return new Envelope(
subject: 'Send O T P',
);
}
public function content(): Content
{
return new Content(
view: 'emails.otp',
);
}
public function attachments(): array
{
return [];
}
}File diatas berkaitan dengan proses pengiriman email, dan bagian subject: adalah subject email yang akan dikirimkan. Sedangkan view: adalah lokasi dari body/template email yang telah dibuat sebelumnya dalam folder emails > otp.blade.php
Step 6. Perbarui Routes Laravel
Untuk memastikan semua fungsi email dapat berjalan dengan baik, silahkan update routes Laravel Anda di file web.php dengan menambahkan konfig berikut:
<?php
use App\Http\Controllers\ProfileController;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
{routes lama Anda}
...
Route::get('/otp-verify', function () {
return view('auth.otp-verify');
})->name('otp.verify.form');
Route::post('/otp-verify', function (Request $req) {
$req->validate(['otp' => 'required|numeric']);
$user = \App\Models\User::find(session('otp_user_id'));
if (!$user || $user->otp_code !== $req->otp || now()->gt($user->otp_expires_at)) {
return back()->withErrors(['otp' => 'OTP salah atau kadaluarsa']);
}
// aktifkan reset OTP disini
$user->otp_code = null;
$user->otp_expires_at = null;
$user->save();
Auth::login($user);
session()->forget('otp_user_id');
return redirect()->route('dashboard');
})->name('otp.verify');
require __DIR__.'/auth.php';
Silahkan sesuaikan script diatas dalam routes Laravel Anda, pastikan bagian OTP berada dibagian bawah setelah route login.
Step 7. Perbarui Controller Auth
Di langkah ke tujuh ini, Anda perlu update file AuthenticatedSessionController.php di folder app\Http\Controllers\Auth. Silahkan sesuaikan default kodenya dengan script di bawah:
<?php
namespace App\Http\Controllers\Auth;
use App\Models\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\LoginRequest;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
use Illuminate\Support\Facades\Mail;
{script default}
...
public function store(LoginRequest $request): RedirectResponse
{
$request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
$user = User::where('email', $request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
throw ValidationException::withMessages([
'email' => __('auth.failed'),
]);
}
if ($user->otp_enabled) {
$otp = rand(100000, 999999);
$user->otp_code = $otp;
$user->otp_expires_at = now()->addMinutes(5);
$user->save();
Mail::to($user->email)->send(new \App\Mail\SendOTP($otp));
session(['otp_user_id' => $user->id]);
return redirect()->route('otp.verify.form');
}
Auth::login($user, $request->boolean('remember'));
$request->session()->regenerate();
return redirect()->intended(RouteServiceProvider::HOME);
}
Silahkan Anda sesuaikan script di atas, jika belum ada maka perlu ditambahkan dan diperbarui.
Step 8. Tambahkan tombol Enable 2FA di Profile
Langkah terakhir, tambahkan tombol 2FA di profile dengan file edit.blade.php yang berada dalam folder \resources\views\profile.
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.update-profile-information-form')
</div>
</div>
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.update-password-form')
</div>
</div>
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
<div class="p-6 text-gray-900 dark:text-gray-100">
@if (!auth()->user()->otp_enabled)
<form method="POST" action="{{ route('otp.enable') }}">
@csrf
<x-primary-button>Aktifkan 2FA Email</x-primary-button>
</form>
@else
<p>2FA melalui Email telah Aktif</p>
@endif
</div>
</div>
</div>
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.delete-user-form')
</div>
</div>
</div>
</div>Apabila semua langkah telah dilakukan, silahkan bersihkan cache dari config, view, route dan lakukan optimize dengan perintah berikut:
php artisan optimizeUntuk hasil pengujiannya bisa Anda lihat pada video berikut.
Apabila semua langkah diatas telah selesai semua, Anda perlu memastikan kembali settingan email di file .ENV telah sesuai untuk mengirim email.
Penutup
Keamanan aplikasi adalah hal yang tidak boleh dianggap sepele. Dengan menerapkan 2FA Login di Laravel, Anda menambahkan lapisan perlindungan ekstra yang mampu mencegah akses ilegal sekaligus meningkatkan kepercayaan pengguna. Jadi, pastikan fitur ini menjadi bagian dari aplikasi Anda agar data tetap aman dan aplikasi terlihat lebih profesional.
Dan jika Anda butuh hosting yang aman sekaligus dilengkapi fitur keamanan lengkap, hosting dari Rumahweb adalah solusinya. Layanan hosting kami sudah dibekali antivirus Monarx, SSL gratis, hingga sistem keamanan berlapis, sehingga jauh lebih aman dibanding hosting standar pada umumnya. Dengan begitu, aplikasi Laravel Anda tidak hanya aman dari sisi kode, tapi juga dari sisi server tempatnya berjalan.
Itu dia panduan kami tentang cara mengaktifkan 2FA login di Laravel framework, semoga bermanfaat.







