Download the PHP package biponix/laravel-secure-otp without Composer
On this page you can find all versions of the php package biponix/laravel-secure-otp. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download biponix/laravel-secure-otp
More information about biponix/laravel-secure-otp
Files in biponix/laravel-secure-otp
Package laravel-secure-otp
Short Description Laravel OTP generator and validator
License MIT
Homepage https://github.com/biponix/laravel-secure-otp
Informations about the package laravel-secure-otp
Laravel Secure OTP
A production-ready, secure OTP (One-Time Password) package for Laravel applications. Generate and verify OTP codes via Email, SMS, WhatsApp, or any Laravel notification channel.
Features
- ✅ Production-Grade Security: HMAC-based storage with secret key, timing-attack resistant verification
- ✅ Multi-Channel Support: Email, SMS, WhatsApp, Telegram (via Laravel Notifications)
- ✅ Pluggable Identifier Types: Extensible validation/normalization for emails, phones, usernames, user IDs, etc.
- ✅ Context-Safe: Works seamlessly in HTTP, queue workers, and console commands
- ✅ Context-Aware Rate Limiting: Separate limits for generation vs verification (brute force protection)
- ✅ Multi-Layer Protection: Per-identifier + per-IP rate limiting in HTTP contexts
- ✅ Attack Prevention: Replay attack prevention, race condition protection with distributed cache locks
- ✅ Fully Customizable: Custom notification classes, configurable expiry, length, attempts
- ✅ Security Logging: Detailed audit logs with privacy-preserving PII masking
- ✅ 100% Test Coverage: 104 comprehensive tests ensuring reliability
- ✅ Wide Compatibility: PHP 8.1-8.4, Laravel 10-12
Installation
You can install the package via composer:
Run the migrations:
The migrations will run automatically from the package. If you need to customize the migration, you can publish it first:
Publish the config file (optional):
Configuration
The config file (config/secure-otp.php) allows you to customize:
Usage
Quick Start
Without Type Validation (Pass-through Mode)
With Type Validation (Recommended for production)
Basic Usage Example
Using with Dependency Injection
Custom Identifier Types
Create custom identifier types for phones, usernames, or any identifier format you need.
Step 1: Create Type Class
Step 2: Register Type in AppServiceProvider
Step 3: Use With Type Parameter
More Examples:
Generate Without Sending (Custom Delivery)
Send Synchronously (Block Until Sent)
Using the Facade (Optional)
Custom Notification Channels
Create your own notification class to route OTPs via SMS, WhatsApp, or other channels based on identifier type.
Type-Based Channel Routing:
Register Your Notification:
Update your .env:
Usage:
Cleanup Expired OTPs
The package requires scheduled cleanup to remove expired OTP records from the database.
Step 1: Add to Laravel Scheduler
In Laravel 11+, add to routes/console.php:
Or in app/Console/Kernel.php (Laravel 10 and below):
Step 2: Ensure Cron is Running
Make sure your server has the Laravel scheduler cron job configured:
Manual Cleanup (Optional)
Programmatic Cleanup (Advanced)
Security Features
1. HMAC-Based Storage (Rainbow Table Protection)
OTP codes are hashed using HMAC-SHA256 with a secret key before storage. This prevents rainbow table attacks even if the database is compromised. Plain codes are never saved.
2. Timing-Safe Comparison
Uses hash_equals() to prevent timing attacks during verification.
3. Context-Aware Rate Limiting (Brute Force Protection)
Separate rate limits for generation vs verification to balance security and user experience:
Generation (Sending OTP)
- Per Identifier: 3 attempts/hour (prevents spam to a user)
- Per IP: 10 attempts/hour (prevents mass spamming from one IP)
Verification (Checking OTP)
- Per Identifier: 5 attempts/minute (more lenient, user may typo)
- Per IP: 20 attempts/minute (prevents distributed brute force across multiple accounts)
Key Features:
- Smart Detection: IP rate limiting automatically skipped in queue/console contexts
- Flexible Configuration: Supports context-specific overrides (
verify_per_identifier) or falls back to shared config - Cache Key Isolation: Uses context-aware keys (e.g.,
secure-otp:verify:identifier:[email protected]) - Per-Axis Control: Each rate limiting axis can be disabled independently by setting to
nullorfalse
4. Generic Responses
Returns boolean values instead of detailed error messages to prevent enumeration attacks.
5. Race Condition Protection
Uses distributed cache locks (Cache::lock()) combined with database transactions and row-level locks (lockForUpdate()) to serialize OTP generation and ensure only one valid OTP exists per identifier at any time. Lock timeouts (3 seconds) provide friendly error messages under high concurrency.
6. Replay Attack Prevention
Previous OTPs are automatically invalidated when a new one is generated.
7. Attempt Limiting
Maximum verification attempts per OTP (default: 3) to prevent brute force attacks.
8. Security Logging with Privacy
Logs all security events (invalid codes, rate limits, etc.) with PII masking:
- Emails:
te***@example.com - Phones:
***7890
API Reference
generate(string $identifier, ?string $type = null): string
Generates an OTP code without sending it (for custom delivery methods).
Parameters:
$identifier(string): Email, phone, username, or any identifier$type(string|null): Optional. Identifier type for validation/normalization (e.g., 'email', 'sms', 'username')
Returns:
string: The generated OTP code
Throws:
RateLimitExceededException: If rate limit is exceededInvalidIdentifierException: If security check fails or type validation failsOtpGenerationException: If OTP generation fails
Examples:
send(string $identifier, ?string $type = null): void
Generates and queues an OTP notification to the given identifier (non-blocking).
Parameters:
$identifier(string): Email, phone, username, or any identifier$type(string|null): Optional. Identifier type for validation/normalization
Returns:
void
Throws:
RateLimitExceededException: If rate limit is exceededInvalidIdentifierException: If security check fails or type validation failsOtpGenerationException: If OTP generation/sending fails
Examples:
sendNow(string $identifier, ?string $type = null): void
Generates and sends an OTP synchronously to the given identifier (blocks until sent).
Parameters:
$identifier(string): Email, phone, username, or any identifier$type(string|null): Optional. Identifier type for validation/normalization
Returns:
void
Throws:
RateLimitExceededException: If rate limit is exceededInvalidIdentifierException: If security check fails or type validation failsOtpGenerationException: If OTP generation/sending fails
verify(string $identifier, string $code, ?string $type = null): bool
Verifies an OTP code for the given identifier.
Parameters:
$identifier(string): Email, phone, username, or any identifier$code(string): The OTP code to verify (default 6 digits)$type(string|null): Optional. Must match the type used insend()for normalization consistency
Returns:
true: OTP verified successfullyfalse: Verification failed (invalid, expired, max attempts exceeded, etc.)
Important: The $type parameter must match what was used when sending the OTP to ensure proper normalization.
Examples:
addType(string $name, OtpIdentifierType $type): void
Register a custom identifier type for validation and normalization.
Parameters:
$name(string): Type name (e.g., 'sms', 'email', 'username')$type(OtpIdentifierType): Type implementation
Example:
cleanupExpired(): int
Deletes expired OTP records older than configured hours.
Returns: Number of deleted records
Testing
The package includes comprehensive tests:
Run tests with coverage (requires PCOV or Xdebug):
The package maintains 100% code coverage with 103 comprehensive tests covering all security features, edge cases, and error scenarios.
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Contributions are welcome! Please see CONTRIBUTING for details.
Security Vulnerabilities
If you discover a security vulnerability, please send an email to [email protected]. All security vulnerabilities will be promptly addressed.
Credits
- Md Ashiquzzaman
- All Contributors
License
The MIT License (MIT). Please see License File for more information.
All versions of laravel-secure-otp with dependencies
spatie/laravel-package-tools Version ^1.16
illuminate/contracts Version ^10.0|^11.0|^12.0|^13.0