adeshsuryan / laravel-otp-login
Adds a one-time password step after Laravel login, with pluggable SMS, mail, log, and array channels.
Requires
- php: ^8.3
- illuminate/auth: ^13.0
- illuminate/contracts: ^13.0
- illuminate/database: ^13.0
- illuminate/http: ^13.0
- illuminate/mail: ^13.0
- illuminate/routing: ^13.0
- illuminate/session: ^13.0
- illuminate/support: ^13.0
Requires (Dev)
- larastan/larastan: ^2.9|^3.0
- laravel/pint: ^1.0
- orchestra/testbench: ^6.40|^7.40|^8.0|^9.0|^10.0|^11.0
- phpstan/phpstan: ^1.12|^2.0
- phpunit/phpunit: ^9.6|^10.5|^11.0|^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-master
- 13.1.1
- 12.1.1
- 12.1.0
- 12.0.3
- 12.0.2
- 12.0.1
- 12.0.0
- 11.1.1
- 11.1.0
- 11.0.3
- 11.0.2
- 11.0.1
- 11.0.0
- 10.1.1
- 10.1.0
- 10.0.3
- 10.0.2
- 10.0.1
- 10.0.0
- 9.1.1
- 9.1.0
- 9.0.3
- 9.0.2
- 9.0.1
- 9.0.0
- 8.1.1
- 8.1.0
- 8.0.3
- 8.0.2
- 8.0.1
- 8.0.0
- 5.13
- 5.12
- 5.11
- 5.10
- 5.9
- 5.8
- 5.7
- 5.6
- 5.5
- 5.4
- 5.3
- 5.2
- 5.1
- 5.0
- 1.2
- 1.1
- 1.0.1
- 1.0
- 0.4
- 0.3
- 0.2
- 0.1
This package is auto-updated.
Last update: 2026-10-18 06:11:57 UTC
README
Adds a one-time password step after a successful Laravel login. Delivery is pluggable: local log / array channels for development and CI, mail for Mailpit or real SMTP, and optional SMS adapters (Twilio, Nexmo/Vonage, Msg91, BioTekno).
Packagist: adeshsuryan/laravel-otp-login
GitHub: adeshsuryan/laravel-otp-login
Choose the right version
Pin the package major to your Laravel major. Legacy tags stay frozen for existing installs.
| Laravel | Package constraint | PHP | Status |
|---|---|---|---|
| 13.x | adeshsuryan/laravel-otp-login:^13.0 |
^8.3 | supported — latest is 13.1.1 |
| 12.x | adeshsuryan/laravel-otp-login:^12.0 |
^8.2 | supported — latest is 12.1.1 |
| 11.x | adeshsuryan/laravel-otp-login:^11.0 |
^8.2 | security fixes shipped in 11.1.1; Laravel 11 itself is EOL — Composer's advisory policy may block it; upgrade Laravel |
| 10.x | adeshsuryan/laravel-otp-login:^10.0 |
^8.1 | security fixes shipped in 10.1.1; Laravel 10 is EOL — upgrade |
| 9.x | adeshsuryan/laravel-otp-login:^9.0 |
^8.0 | security fixes shipped in 9.1.1; Laravel 9 and PHP 8.0 are EOL — upgrade |
| 8.x | adeshsuryan/laravel-otp-login:^8.0 |
^7.3|^8.0 | security fixes shipped in 8.1.1; Laravel 8 and PHP ≤8.1 are EOL — upgrade |
| 5.x | adeshsuryan/laravel-otp-login:5.13 (or 5.8, …) |
historical | frozen |
EOL note: Composer's default
policy.advisories.blocknow refuses to install Laravel majors whose entire line carries security advisories (8/9/10/11). The package tags for those lines remain for pinned applications; they are not a recommendation to stay on an EOL framework.
# Modern composer require adeshsuryan/laravel-otp-login:^12.0 # Legacy Laravel 5 app — do not jump to ^12 composer require adeshsuryan/laravel-otp-login:5.13
Tags 0.1–5.13 are immutable historical releases for older Laravel 5-era apps.
Install (Laravel 8–13)
composer require adeshsuryan/laravel-otp-login:^12.0 php artisan vendor:publish --tag=otp-config php artisan migrate
Package discovery registers OTPServiceProvider automatically.
Environment
OTP_SERVICE_ENABLED=true OTP_SERVICE=log OTP_TIMEOUT=600 OTP_DIGIT_LENGTH=6 OTP_USER_PHONE_FIELD=phone OTP_AFTER_LOGIN_REDIRECT=/home # Security controls (defaults since *.1.0) OTP_ENCODE_PASSWORD=true # OTPs stored hashed, not plaintext OTP_MAX_ATTEMPTS=5 # wrong codes before the OTP is discarded OTP_VERIFY_THROTTLE=10,1 # route throttle: max 10 requests / minute OTP_FAIL_OPEN=false # keep false — true admits users with no OTP
For CI and automated browsers use OTP_SERVICE=array or OTP_SERVICE=mail with Mailpit. Do not put Twilio/Nexmo keys in the test matrix.
Upgrading from *.0.x? Read UPGRADING.md — *.1.0
changes storage defaults and the trusted-device cookie, and adds a migration.
After password login
Create a waiting OTP and send it:
use adeshsuryan\LaravelOTPLogin\OneTimePassword; $otp = OneTimePassword::create([ 'user_id' => $user->id, 'status' => 'waiting', ]); $otp->send($user); // redirect to route('otp.view')
Routes (middleware web + auth):
GET /login/verify→otp.viewPOST /login/check→otp.verify
Optional middleware alias: otp.verified.
Channels
| Key | Use |
|---|---|
log |
Default. Writes OTP to the Laravel log (and caches last OTP for tests). |
array |
Cache only. Best for PHPUnit. |
mail |
Laravel Mail (pair with Mailpit in Docker). |
twilio / nexmo / msg91 / biotekno |
Optional production SMS. |
Custom channel: implement adeshsuryan\LaravelOTPLogin\ServiceInterface and register the class under config/otp.php → services.
Tests
composer install
composer test
License
MIT. See LICENSE.md. Maintained by Adesh Kumar.
