Introduction
One of the essential features in modern applications is OTP verification for securing user logins and sensitive actions. In this post, we’ll walk through how to implement OTP verification in FilamentPHP 3 (Laravel 12) while ensuring that:
✅ The OTP verification page is full-screen (no sidebar, no topbar)
✅ The system correctly validates OTPs
✅ Users redirect properly after verification (fixing “Route [filament.admin.pages.dashboard] not defined” error)
✅ Email settings are configured to send OTPs
Imperdiet nulla malesuada pellentesque elit eget gravida cum. Malesuada fames ac turpis egestas integer eget aliquet. Fames ac turpis egestas sed tempus urna et pharetra. Vulputate sapien nec sagittis aliquam.
1️⃣ Install the Laravel OTP Package
To generate and validate OTPs, we’ll use the ichtrojan/laravel-otp package. Run the following command:
bash composer require ichtrojan/laravel-otp
Next, publish the package configuration file:
bash php artisan vendor:publish –provider=”Ichtrojan\Otp\OtpServiceProvider”
This will create an otp.php config file in config/otp.php.
2️⃣ Configure Email Settings
Since the OTP will be sent via email, ensure your .env file contains correct mail configuration:
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_username
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=no-reply@yourapp.com
MAIL_FROM_NAME=”Your App Name”
Replace the above values with your actual SMTP credentials (e.g., from Mailtrap, SendGrid, or your preferred email service).
3️⃣ Create the OTP Verification Page in Filament
Now, let’s create a custom OTP verification page.
Run the following command:
bash php artisan make:filament-page OTPVerification
This creates app/Filament/Pages/OTPVerification.php. Open this file and modify it:
✅ Full-Screen OTP Verification Page
📌 app/Filament/Pages/OTPVerification.php
php namespace App\Filament\Pages;
use Filament\Pages\Page;
use Filament\Facades\Filament;
use Filament\Forms\Form;
use Filament\Forms\Components\TextInput;
use Ichtrojan\Otp\Otp;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
use Illuminate\Http\RedirectResponse;
class OTPVerification extends Page
{
protected static ?string $navigationIcon = ‘heroicon-o-lock-closed’;
protected static string $view = ‘filament.pages.otp-verification’;
public static function shouldRegisterNavigation(): bool
{
return false; // Hide from sidebar
}
public function mount(): void
{
Filament::getPanel()->navigation(false); // Hide sidebar
}
public function getHeader(): ?string
{
return null; // Hide topbar
}
public function form(Form $form): Form
{
return $form->schema([
TextInput::make(‘otp’)
->label(‘Enter OTP’)
->numeric()
->required()
->minLength(6)
->maxLength(6),
]);
}
public function verifyOtp(): RedirectResponse
{
$otp = new Otp();
$user = Auth::user();
$verification = $otp->validate($user->email, request(‘otp’));
if (!$verification->status) {
session()->flash(‘error’, ‘Invalid OTP. Please try again.’);
return back();
}
// Redirect to the correct panel dashboard
return redirect()->to(Filament::getPanel()->getUrl());
}
}
4️⃣ Create the OTP Verification Blade View
Now, let’s design the OTP page using TailwindCSS.
📌 resources/views/filament/pages/otp-verification.blade.php
blade
CopyEdit
@extends(‘filament::components.layouts.base’)
@section(‘title’, ‘OTP Verification’)
@section(‘body’)
<div class=”flex items-center justify-center min-h-screen bg-gray-100 dark:bg-gray-900″>
<div class=”w-full max-w-md p-6 bg-white dark:bg-gray-800 rounded-lg shadow-md”>
<h2 class=”text-2xl font-bold text-center text-gray-900 dark:text-gray-100″>OTP Verification</h2>
<p class=”text-sm text-center text-gray-600 dark:text-gray-400 mb-4″>
Enter the 6-digit code sent to your email.
</p>
<form wire:submit.prevent=”verifyOtp”>
{{ $this->form }}
<button type=”submit”
class=”w-full px-4 py-2 mt-4 text-white bg-blue-600 rounded-lg hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600″>
Verify OTP
</button>
</form>
<p class=”text-xs text-center text-gray-500 dark:text-gray-400 mt-4″>
Didn’t receive the code? <a href=”#” class=”text-blue-600 dark:text-blue-400″>Resend</a>
</p>
</div>
</div>
@endsection
5️⃣ Send OTP to Users
To send an OTP when a user logs in or registers, modify your authentication flow:
📌 Example: Send OTP after login
php
CopyEdit
use Ichtrojan\Otp\Otp;
use Illuminate\Support\Facades\Mail;
public function sendOtp()
{
$otp = new Otp();
$user = Auth::user();
$otpData = $otp->generate($user->email, ‘numeric’, 6);
Mail::raw(“Your OTP code is: ” . $otpData->token, function ($message) use ($user) {
$message->to($user->email)
->subject(“Your OTP Verification Code”);
});
return redirect()->route(‘filament.pages.otp-verification’);
}
6️⃣ Fixing “Route [filament.admin.pages.dashboard] Not Defined”
After OTP verification, Filament may try to redirect users to filament.admin.pages.dashboard, which doesn’t exist if your panel is named differently.
✅ Fix: Redirect dynamically to the correct dashboard Modify verifyOtp():
php
CopyEdit
return redirect()->to(Filament::getPanel()->getUrl());
This ensures the user lands on the correct Filament dashboard.
Final Step: Clear Cache
To apply changes, run:
bash
CopyEdit
php artisan route:clear
php artisan cache:clear
php artisan config:clear
🎯 Summary
✅ Installed ichtrojan/laravel-otp for OTP generation
✅ Configured email settings in .env
✅ Created a full-screen OTP page (no sidebar, no topbar)
✅ Implemented OTP verification & redirection
✅ Fixed Filament redirect errors
🚀 Conclusion
With this setup, you now have a secure OTP verification system in FilamentPHP. This ensures users verify their identity before accessing the dashboard. Let me know in the comments if you have any issues or need improvements! 🎉🚀