daikazu/laravel-frontdoor
Passwordless auth for Laravel: users sign in with one-time email codes. Session-based, no migrations required. Driver-based account providers (includes testing driver), optional registration, Livewire components, rate limiting, events, and deterministic avatars.
Installation:
composer require daikazu/laravel-frontdoor
Publish the config:
php artisan vendor:publish --provider="Daikazu\Frontdoor\FrontdoorServiceProvider" --tag="config"
Configure:
Update .env with your mail driver (e.g., MAIL_MAILER=smtp) and configure config/frontdoor.php:
'driver' => env('FRONTDOOR_DRIVER', 'testing'), // Use 'testing' for dev, 'email' for production
'code_length' => 6,
'code_expiry' => 10, // minutes
First Use Case: Trigger a login flow in a controller:
use Daikazu\Frontdoor\Facades\Frontdoor;
public function login()
{
$email = request()->input('email');
Frontdoor::sendCode($email); // Sends OTP via email
return response()->json(['message' => 'Code sent']);
}
config/frontdoor.php (customize drivers, code settings).Daikazu\Frontdoor\Facades\Frontdoor (core methods like sendCode(), verifyCode()).Initiate Login:
Frontdoor::sendCode($userEmail); // Triggers email dispatch
.env).frontdoor:{email}).Verify Code:
$isValid = Frontdoor::verifyCode($email, $userSubmittedCode);
if ($isValid) {
// Authenticate user (session-based)
auth()->loginUsingId($userId); // Manually handle if not using built-in auth
}
Custom Account Providers:
Extend Daikazu\Frontdoor\Contracts\AccountProvider:
class CustomProvider implements AccountProvider {
public function getUserByEmail(string $email): ?User {
return User::where('email', $email)->first(); // Custom logic
}
}
Register in config/frontdoor.php:
'providers' => [
'default' => \App\Providers\CustomProvider::class,
],
Laravel Auth Integration: Use middleware to protect routes:
Route::middleware(['auth', 'verified'])->group(function () {
// Protected routes
});
Override auth() logic in app/Providers/AuthServiceProvider.php to use Frontdoor::verifyCode().
Rate Limiting:
Add rate limiting to sendCode() calls (e.g., via throttle middleware):
Route::post('/login', [LoginController::class, 'sendCode'])
->middleware('throttle:5,1'); // 5 requests per minute
Testing:
Use the testing driver in .env:
FRONTDOOR_DRIVER=testing
Mock emails with:
$this->artisan('frontdoor:flush'); // Clear cached codes
Cache Expiry:
code_expiry minutes (default: 10). Ensure users submit codes promptly.Artisan::call('cache:table'); (if using database cache).Email Delivery:
Frontdoor::testing()->assertCodeSent($email).MAIL_* env vars are correct. Test with a real email first.Session Handling:
SESSION_DRIVER=file (or another driver) is set in .env.auth.user) must be manually set after verifyCode().Email Validation:
$request->validate(['email' => 'required|email']);
Log Codes:
Enable debug mode in config/frontdoor.php:
'debug' => env('FRONTDOOR_DEBUG', false),
Logs codes to storage/logs/laravel.log.
Clear Cache: Flush codes manually:
php artisan frontdoor:flush
Or via facade:
Frontdoor::flushCodes();
Custom Drivers:
Create a driver by implementing Daikazu\Frontdoor\Contracts\CodeSender:
class SlackSender implements CodeSender {
public function send(string $email, string $code): void {
// Send via Slack API
}
}
Register in config/frontdoor.php:
'drivers' => [
'slack' => \App\Services\SlackSender::class,
],
Code Generation: Override the default random code generator:
Frontdoor::setCodeGenerator(function () {
return Str::random(6); // Custom logic
});
Event Listeners:
Listen for code events (e.g., CodeSent, CodeVerified) in EventServiceProvider:
protected $listen = [
\Daikazu\Frontdoor\Events\CodeSent::class => [
\App\Listeners\LogCodeSent::class,
],
];
driver key in config is case-sensitive. Use 'testing' (not 'Testing').SANCTUM_STATEFUL_DOMAINS or SESSION_DOMAIN is configured for session persistence.How can I help you explore Laravel packages today?