[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"package:filament-otp-login":3},{"type":4,"package":5,"activeDoc":11,"seo":112,"alternates":114,"editable":117},"package",{"id":6,"title":7,"slug":8,"url":9,"excerpt":10,"formatted_price":11,"type":12,"github_url":15,"external_url":11,"plumb":16,"category":24,"tags":28,"cover":11,"blocks":38,"toc":76,"docs":111},4,"OTP Login","filament-otp-login","\u002Fpackages\u002Ffilament-otp-login","Add simple, passwordless-capable OTP authentication to FilamentPHP panels.",null,{"value":13,"label":14},"free","Free","https:\u002F\u002Fgithub.com\u002Fafsakar\u002Ffilament-otp-login",{"version":17,"security":18,"abandoned":19,"composite":20,"ecosystem":21,"checked_at":22,"maintenance":21,"url":23},"v2.0.0",67.57,false,82.16,100,"2026-08-14T22:25:15+00:00","https:\u002F\u002Fplumbphp.dev\u002Fafsakar\u002Ffilament-otp-login",{"id":25,"title":26,"slug":27},3,"FilamentPHP","filamenetphp",[29,32,35],{"id":30,"title":31,"slug":31},15,"v3",{"id":33,"title":34,"slug":34},13,"v4",{"id":36,"title":37,"slug":37},14,"v5",[39,43,46,49,52,55,58,61,64,67,70,73],{"type":40,"data":41},"general.rich-text",{"content":42},"\u003Cdiv class=\"filament-hidden\">\n    \u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Fafsakar\u002Ffilament-otp-login\u002Frefs\u002Fheads\u002Fv2\u002Fassets\u002Fafsakar-otp-login.png\" alt=\"OTP Login for FilamentPHP\">\n\u003C\u002Fdiv>\n\u003Cp>This package is an OTP Login for FilamentPHP. It is a simple package that allows you to login to your FilamentPHP application using OTP.\u003C\u002Fp>",{"type":40,"data":44},{"content":45},"\u003Ch2 id=\"installation\">Installation\u003C\u002Fh2>\n\u003Cp>You can install the package via composer:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">composer require afsakar\u002Ffilament-otp-login\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>You can publish and run the migrations with:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">php artisan vendor:publish --tag=&quot;filament-otp-login-migrations&quot;\nphp artisan migrate\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>You can publish the translations files with:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">php artisan vendor:publish --tag=&quot;filament-otp-login-translations&quot;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Optionally, you can publish the views using\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">php artisan vendor:publish --tag=&quot;filament-otp-login-views&quot;\n\u003C\u002Fcode>\u003C\u002Fpre>",{"type":40,"data":47},{"content":48},"\u003Ch2 id=\"upgrade-guide\">Upgrade Guide\u003C\u002Fh2>\n\u003Cp>This release targets Filament \u003Ccode>^4.0 || ^5.0\u003C\u002Fcode> and PHP \u003Ccode>^8.2\u003C\u002Fcode>. Filament v2\u002Fv3 projects must upgrade Filament before upgrading this package.\u003C\u002Fp>\n\u003Cp>Configuration moved from the config file to \u003Ccode>FilamentOtpLoginPlugin\u003C\u002Fcode>, so define settings per panel:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">FilamentOtpLoginPlugin::make()\n    -&gt;otpCode(length: 6, expiresIn: 120)\n    -&gt;rateLimit(attempts: 5, decaySeconds: 60)\n    -&gt;resendLimit(attempts: 3, decaySeconds: 300)\n    -&gt;passwordless(false)\n    -&gt;notification(\\Afsakar\\FilamentOtpLogin\\Notifications\\SendOtpCode::class);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>The published config file is intentionally empty.\u003C\u002Fp>\n\u003Cp>If you published the login views, publish them again or update them for Filament v4\u002Fv5 components and translation namespaces. The package now uses Filament's native \u003Ccode>OneTimeCodeInput\u003C\u002Fcode>, so remove any custom references to \u003Ccode>Afsakar\\FilamentOtpLogin\\Filament\\Forms\\OtpInput\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Cp>The OTP table column changed from \u003Ccode>email\u003C\u002Fcode> to \u003Ccode>identifier\u003C\u002Fcode>. Publish and run the new migration, or add this to your own upgrade migration:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">Schema::table('otp_codes', function (Blueprint $table) {\n    $table-&gt;renameColumn('email', 'identifier');\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>OTP codes are now stored as hashes. Any active OTP code created before the upgrade will no longer verify; users can request a new code.\u003C\u002Fp>",{"type":40,"data":50},{"content":51},"\u003Ch2 id=\"usage\">Usage\u003C\u002Fh2>\n\u003Cp>Just register the \u003Ccode>Afsakar\\FilamentOtpLogin\\FilamentOtpLoginPlugin\u003C\u002Fcode> plugin in the your panel provider file.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">use Afsakar\\FilamentOtpLogin\\FilamentOtpLoginPlugin;\n\n    public function panel(Panel $panel): Panel\n    {\n        return $panel\n            -&gt;plugins([\n                FilamentOtpLoginPlugin::make()\n                    -&gt;otpCode(length: 6, expiresIn: 120)\n                    -&gt;rateLimit(attempts: 5, decaySeconds: 60)\n                    -&gt;resendLimit(attempts: 3, decaySeconds: 300),\n            ]);\n    }\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>For phone based login:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">FilamentOtpLoginPlugin::make()\n    -&gt;identifierFormField('phone', label: 'Phone', type: 'tel')\n    -&gt;userIdentifierColumn('phone');\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Use \u003Ccode>-&gt;tableName()\u003C\u002Fcode>, \u003Ccode>-&gt;identifierColumn()\u003C\u002Fcode>, \u003Ccode>-&gt;userModel()\u003C\u002Fcode>, \u003Ccode>-&gt;passwordless()\u003C\u002Fcode>, and \u003Ccode>-&gt;notification()\u003C\u002Fcode> when a panel needs different behavior.\u003C\u002Fp>\n\u003Cp>If you want to ignore specific user groups from OTP login just implement the \u003Ccode>Afsakar\\FilamentOtpLogin\\Models\\Contracts\\CanLoginDirectly\u003C\u002Fcode> trait in your User model.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">use Afsakar\\FilamentOtpLogin\\Models\\Contracts\\CanLoginDirectly;\n\nclass User extends Authenticatable implements CanLoginDirectly\n{\n    use HasFactory, Notifiable;\n\n    \u002F\u002F other user model code\n\n    public function canLoginDirectly(): bool\n    {\n        return str($this-&gt;email)-&gt;endsWith('@example.com');\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cem>\u003Cem>Note:\u003C\u002Fem> For medium and large scale applications, you only need to run &quot;php artisan model:prune&quot; command as cron to prevent the otp_code table from bloating and performance issues.\u003C\u002Fem>\u003C\u002Fp>\n\u003Cp>OTP codes are hashed before they are stored in the database.\u003C\u002Fp>\n\u003Cp>To enable passwordless login, call \u003Ccode>-&gt;passwordless()\u003C\u002Fcode>. When enabled, users log in with the configured identifier and OTP only.\u003C\u002Fp>",{"type":40,"data":53},{"content":54},"\u003Ch2 id=\"custom-login-page\">Custom Login Page\u003C\u002Fh2>\n\u003Cp>If you want to customize the login page, you can extend the \u003Ccode>\\Afsakar\\FilamentOtpLogin\\Filament\\Pages\\Login\u003C\u002Fcode> page and set your custom login page to plugin in the panel provider file with \u003Ccode>loginPage\u003C\u002Fcode> method.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">&lt;?php\n\nnamespace App\\Filament\\Pages;\n\nuse Afsakar\\FilamentOtpLogin\\Filament\\Pages\\Login as OtpLogin;\nuse Illuminate\\Contracts\\Support\\Htmlable;\n\nclass OverrideLogin extends OtpLogin\n{\n    public function getHeading(): string | Htmlable\n    {\n        return 'Example Login Heading';\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cpre>\u003Ccode class=\"language-php\">use App\\Filament\\Pages\\OverrideLogin;\n\n    public function panel(Panel $panel): Panel\n    {\n        return $panel\n            -&gt;plugins([\n                FilamentOtpLoginPlugin::make()\n                    -&gt;loginPage(OverrideLogin::class),\n            ]);\n    }\n\u003C\u002Fcode>\u003C\u002Fpre>",{"type":40,"data":56},{"content":57},"\u003Ch2 id=\"custom-notification-class\">Custom Notification Class\u003C\u002Fh2>\n\u003Cp>If you want to customize the notification, you can replace the \u003Ccode>\\Afsakar\\FilamentOtpLogin\\Notifications\\SendOtpCode\u003C\u002Fcode> with your own.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">&lt;?php\n\nnamespace App\\Notifications;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Notifications\\Messages\\MailMessage;\nuse Illuminate\\Notifications\\Notification;\n\nclass SendOtpCode extends Notification\n{\n    use Queueable;\n\n    \u002F**\n     * Create a new notification instance.\n     *\n     * @return void\n     *\u002F\n    public function __construct(public string $code, public int $expiresIn)\n    {\n        \u002F\u002F\n    }\n\n    \u002F**\n     * Get the notification's delivery channels.\n     *\n     * @param  mixed  $notifiable\n     * @return array\n     *\u002F\n    public function via($notifiable)\n    {\n        return ['mail'];\n    }\n\n    \u002F**\n     * Get the mail representation of the notification.\n     *\n     * @param  mixed  $notifiable\n     * @return \\Illuminate\\Notifications\\Messages\\MailMessage\n     *\u002F\n    public function toMail($notifiable)\n    {\n        return (new MailMessage)\n            -&gt;subject(__('filament-otp-login::translations.mail.subject'))\n            -&gt;greeting(__('filament-otp-login::translations.mail.greeting'))\n            -&gt;line(__('filament-otp-login::translations.mail.line1', ['code' =&gt; $this-&gt;code]))\n            -&gt;line(__('filament-otp-login::translations.mail.line2', ['seconds' =&gt; $this-&gt;expiresIn]))\n            -&gt;line(__('filament-otp-login::translations.mail.line3'))\n            -&gt;salutation(__('filament-otp-login::translations.mail.salutation', ['app_name' =&gt; config('app.name')]));\n    }\n\n}\n\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Then update the plugin to use your custom notification class.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">FilamentOtpLoginPlugin::make()\n    -&gt;notification(\\App\\Notifications\\SendOtpCode::class);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>For SMS or WhatsApp, install the provider notification channel in your application, return that channel from \u003Ccode>via()\u003C\u002Fcode>, and use the configured identifier as the recipient.\u003C\u002Fp>",{"type":40,"data":59},{"content":60},"\u003Ch2 id=\"testing\">Testing\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-bash\">composer test\n\u003C\u002Fcode>\u003C\u002Fpre>",{"type":40,"data":62},{"content":63},"\u003Ch2 id=\"changelog\">Changelog\u003C\u002Fh2>\n\u003Cp>Please see \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fafsakar\u002Ffilament-otp-login\u002Fblob\u002Fv2\u002FCHANGELOG.md\">CHANGELOG\u003C\u002Fa> for more information on what has changed recently.\u003C\u002Fp>",{"type":40,"data":65},{"content":66},"\u003Ch2 id=\"contributing\">Contributing\u003C\u002Fh2>\n\u003Cp>Please see \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fafsakar\u002Ffilament-otp-login\u002Fblob\u002Fv2\u002F.github\u002FCONTRIBUTING.md\">CONTRIBUTING\u003C\u002Fa> for details.\u003C\u002Fp>",{"type":40,"data":68},{"content":69},"\u003Ch2 id=\"security-vulnerabilities\">Security Vulnerabilities\u003C\u002Fh2>\n\u003Cp>Please review \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fafsakar\u002Ffilament-otp-login\u002Fblob\u002Fv2\u002F..\u002F..\u002Fsecurity\u002Fpolicy\">our security policy\u003C\u002Fa> on how to report security vulnerabilities.\u003C\u002Fp>",{"type":40,"data":71},{"content":72},"\u003Ch2 id=\"credits\">Credits\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fafsakar\">Azad Furkan ŞAKAR\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fafsakar\u002Ffilament-otp-login\u002Fblob\u002Fv2\u002F..\u002F..\u002Fcontributors\">All Contributors\u003C\u002Fa>\u003C\u002Fli>\n\u003C\u002Ful>",{"type":40,"data":74},{"content":75},"\u003Ch2 id=\"license\">License\u003C\u002Fh2>\n\u003Cp>The MIT License (MIT). Please see \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fafsakar\u002Ffilament-otp-login\u002Fblob\u002Fv2\u002FLICENSE.md\">License File\u003C\u002Fa> for more information.\u003C\u002Fp>",[77,81,84,87,90,93,96,99,102,105,108],{"id":78,"label":79,"level":80},"installation","Installation",2,{"id":82,"label":83,"level":80},"upgrade-guide","Upgrade Guide",{"id":85,"label":86,"level":80},"usage","Usage",{"id":88,"label":89,"level":80},"custom-login-page","Custom Login Page",{"id":91,"label":92,"level":80},"custom-notification-class","Custom Notification Class",{"id":94,"label":95,"level":80},"testing","Testing",{"id":97,"label":98,"level":80},"changelog","Changelog",{"id":100,"label":101,"level":80},"contributing","Contributing",{"id":103,"label":104,"level":80},"security-vulnerabilities","Security Vulnerabilities",{"id":106,"label":107,"level":80},"credits","Credits",{"id":109,"label":110,"level":80},"license","License",[],{"html":113},"\u003Ctitle>FilamentPHP OTP Login Plugin - Azad Furkan Şakar\u003C\u002Ftitle>\n\u003Cmeta name=\"description\" content=\"Add simple, passwordless-capable OTP authentication to FilamentPHP panels.\">\n\u003Cmeta name=\"keywords\" content=\"laravel, backend, developer, php\">\n\u003Clink rel=\"canonical\" href=\"https:\u002F\u002Fafsakar.dev\u002Fpackages\u002Ffilament-otp-login\">\n\u003Clink rel=\"alternate\" hreflang=\"en\" href=\"https:\u002F\u002Fafsakar.dev\u002Fpackages\u002Ffilament-otp-login\">\n\u003Clink rel=\"alternate\" hreflang=\"tr\" href=\"https:\u002F\u002Fafsakar.dev\u002Ftr\u002Fpaketler\u002Ffilament-otp-login\">\n\u003Clink rel=\"alternate\" hreflang=\"x-default\" href=\"https:\u002F\u002Fafsakar.dev\u002Fpackages\u002Ffilament-otp-login\">\n\u003Cmeta name=\"robots\" content=\"index, follow\">\n\u003Cmeta property=\"og:title\" content=\"FilamentPHP OTP Login Plugin\">\n\u003Cmeta property=\"og:description\" content=\"Add simple, passwordless-capable OTP authentication to FilamentPHP panels.\">\n\u003Cmeta property=\"og:type\" content=\"website\">\n\u003Cmeta property=\"og:site_name\" content=\"Azad Furkan Şakar\">\n\u003Cmeta property=\"og:url\" content=\"https:\u002F\u002Fafsakar.dev\u002Fpackages\u002Ffilament-otp-login\">\n\u003Cmeta property=\"og:image\" content=\"https:\u002F\u002Fafsakar.dev\u002Fstorage\u002Fog-images\u002Fpackages\u002F4-en.png\">\n\n\u003Cmeta name=\"twitter:site\" content=\"afsakar\">\n\u003Cmeta name=\"twitter:card\" content=\"summary_large_image\">\n\u003Cmeta name=\"twitter:image\" content=\"https:\u002F\u002Fafsakar.dev\u002Fstorage\u002Fog-images\u002Fpackages\u002F4-en.png\">\n\u003Cmeta name=\"twitter:title\" content=\"FilamentPHP OTP Login Plugin\">\n\u003Cmeta name=\"twitter:description\" content=\"Add simple, passwordless-capable OTP authentication to FilamentPHP panels.\">\n\u003Cmeta name=\"twitter:url\" content=\"https:\u002F\u002Fafsakar.dev\u002Fpackages\u002Ffilament-otp-login\">\n\u003Cscript type=\"application\u002Fld+json\">{\"@context\":\"https:\u002F\u002Fschema.org\",\"@type\":\"WebPage\",\"name\":\"FilamentPHP OTP Login Plugin\",\"description\":\"Add simple, passwordless-capable OTP authentication to FilamentPHP panels.\",\"url\":\"https:\u002F\u002Fafsakar.dev\u002Fpackages\u002Ffilament-otp-login\",\"image\":\"https:\u002F\u002Fafsakar.dev\u002Fstorage\u002Fog-images\u002Fpackages\u002F4-en.png\",\"mainEntityOfPage\":{\"@type\":\"WebPage\",\"@id\":\"https:\u002F\u002Fafsakar.dev\u002Fpackages\u002Ffilament-otp-login\"}}\u003C\u002Fscript>\u003Cscript type=\"application\u002Fld+json\">{\"@context\":\"https:\u002F\u002Fschema.org\",\"@type\":\"BreadcrumbList\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\u002F\u002Fafsakar.dev\u002F\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Packages\",\"item\":\"https:\u002F\u002Fafsakar.dev\u002Fpackages\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"OTP Login\",\"item\":\"https:\u002F\u002Fafsakar.dev\u002Fpackages\u002Ffilament-otp-login\"}]}\u003C\u002Fscript>\u003Cscript type=\"application\u002Fld+json\">{\"@context\":\"https:\u002F\u002Fschema.org\",\"@type\":\"Person\",\"name\":\"Azad Furkan Şakar\",\"url\":\"https:\u002F\u002Fafsakar.dev\",\"@id\":\"https:\u002F\u002Fafsakar.dev\u002F#person\",\"jobTitle\":\"Backend Developer\",\"image\":\"https:\u002F\u002Fafsakar.dev\u002Fstorage\u002Fsettings\u002Fseo\u002F01KZB422BTYXF3J7XS1J2X8GYZ.jpeg\",\"sameAs\":[\"https:\u002F\u002Fx.com\u002Fafsakar\",\"https:\u002F\u002Flinkedin.com\u002Fin\u002Fafsakar\",\"https:\u002F\u002Fgithub.com\u002Fafsakar\"]}\u003C\u002Fscript>",{"en":115,"tr":116},"https:\u002F\u002Fafsakar.dev\u002Fpackages\u002Ffilament-otp-login","https:\u002F\u002Fafsakar.dev\u002Ftr\u002Fpaketler\u002Ffilament-otp-login",{"type":4,"id":6}]