taha-moghaddam/filament-otp-login
OTP (One-Time Password) login for Filament v5: mobile/phone number login with OTP code, no password, no session (mobile passed in URL). Users can “register” by logging in with OTP for the first time.
?mobile=...) to the OTP verification page.request_block_seconds: time (in seconds) before the same mobile can request another OTP.OtpSenderInterface (SMS, email, log, etc.) and set it in config.composer require taha-moghaddam/filament-otp-login
Your user model (e.g. App\Models\AdminUser) must have at least:
mobile) – unique, stored as string or bigInteger.otp_code (nullable int), otp_expires_at (nullable timestamp), otp_sent_count (int, default 0), mobile_verified_at (nullable timestamp).Example migration for admin_users:
Schema::create('admin_users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->unsignedBigInteger('mobile')->unique();
$table->timestamp('mobile_verified_at')->nullable();
$table->unsignedSmallInteger('otp_code')->nullable();
$table->timestamp('otp_expires_at')->nullable();
$table->unsignedTinyInteger('otp_sent_count')->default(0);
$table->rememberToken();
$table->timestamps();
});
php artisan vendor:publish --tag="filament-otp-login-migrations"
php artisan migrate
php artisan vendor:publish --tag="filament-otp-login-config"
Then edit config/filament-otp-login.php:
App\Models\AdminUser).admin_otp_logs).admin_user_id).mobile).FilamentOtpLogin\Contracts\OtpSenderInterface (default: LogOtpSender – logs to Laravel log).In your Filament panel provider (e.g. AdminPanelProvider):
use FilamentOtpLogin\FilamentOtpLoginPlugin;
public function panel(Panel $panel): Panel
{
return $panel
->id('admin')
->path('admin')
->authGuard('admin') // use the guard that uses your user model
->plugins([
FilamentOtpLoginPlugin::make(),
])
// ... rest of panel config
;
}
Do not call ->login() or ->registration() on the panel; the plugin sets the login page and disables registration.
Ensure config/auth.php has a guard that uses your user model, e.g.:
'guards' => [
'admin' => [
'driver' => 'session',
'provider' => 'admin_users',
],
],
'providers' => [
'admin_users' => [
'driver' => 'eloquent',
'model' => App\Models\AdminUser::class,
],
],
| Key | Description | Default |
|---|---|---|
FILAMENT_OTP_LOGIN_USER_MODEL |
User model class | App\Models\AdminUser |
FILAMENT_OTP_LOGIN_OTP_LOG_TABLE |
OTP logs table name | admin_otp_logs |
FILAMENT_OTP_LOGIN_USER_FOREIGN_KEY |
FK column in OTP logs | admin_user_id |
FILAMENT_OTP_LOGIN_MOBILE_COLUMN |
Mobile column on user | mobile |
FILAMENT_OTP_LOGIN_SENDER |
OTP sender class | FilamentOtpLogin\Services\LogOtpSender |
FILAMENT_OTP_LOGIN_OTP_LENGTH |
OTP code length | 6 |
FILAMENT_OTP_LOGIN_OTP_EXPIRES_SECONDS |
OTP validity (seconds) | 120 |
FILAMENT_OTP_LOGIN_REQUEST_BLOCK_SECONDS |
Block before next request (seconds) | 60 |
FILAMENT_OTP_LOGIN_SAME_OTP_MAX_SENDS |
Same code resend limit | 3 |
Implement FilamentOtpLogin\Contracts\OtpSenderInterface:
use FilamentOtpLogin\Contracts\OtpSenderInterface;
use Illuminate\Contracts\Auth\Authenticatable;
class MySmsOtpSender implements OtpSenderInterface
{
public function send(Authenticatable $user, string $code): void
{
$mobile = $user->mobile; // or $user->{config('filament-otp-login.mobile_column')}
// Send SMS to $mobile with $code
}
}
Register it in config:
'sender' => \App\Services\MySmsOtpSender::class,
Publish and edit translations:
php artisan vendor:publish --tag="filament-otp-login-translations"
Keys are under resources/lang/vendor/filament-otp-login/ (e.g. en/filament-otp-login.php). English and Persian (fa) are included in the package.
request_block_seconds), user found or created, OTP generated or same code resent (up to same_otp_max_sends), OTP sent via OtpSenderInterface, redirect to phone-verification-prompt?mobile=....No session is used for the “pending” user; the mobile in the URL identifies the user on the OTP page.
request_block_seconds).See Releases.
MIT. See LICENSE.md.
taha-moghaddam/filament-otp-login).filament-otp-login folder to GitHub.This plugin is built for Filament v5.
How can I help you explore Laravel packages today?