Security Auth - v1.0.0
Account Lockout
AccountLockoutManager (bound to AccountLockoutInterface) handles both user-level and IP-level lockouts driven by failed-attempt counts.
Recording a failed attempt
Trigger from your login flow:
use ArtisanPackUI\SecurityAuth\Authentication\Contracts\AccountLockoutInterface;
$lockoutManager = app( AccountLockoutInterface::class );
// On failed login
$result = $lockoutManager->recordFailedAttempt(
trigger: 'login',
user: $user, // optional — pass null for anonymous attempts
ipAddress: $request->ip(),
);
// $result contains: ['locked' => bool, 'attempts' => int, 'remaining' => int]
if ( $result['locked'] ) {
// user just hit the lockout threshold — refuse login
}
If the attempt threshold is hit within the configured window, recordFailedAttempt automatically locks the user (and the IP if lockout_ip is on).
Clearing failed attempts
On successful login, clear the counter:
$lockoutManager->clearFailedAttempts(
user: $user,
ipAddress: $request->ip(),
);
Manual locks
$lockoutManager->lockUser(
user: $user,
reason: 'Suspicious activity detected',
lockoutType: 'temporary', // temporary | permanent
durationMinutes: 60,
metadata: ['source' => 'admin'],
);
$lockoutManager->lockIp(
ipAddress: $ip,
durationMinutes: 240,
reason: 'Credential stuffing detected',
);
Checking lock state
if ( $lockoutManager->isUserLocked( $user ) ) {
abort(403, 'Account locked');
}
if ( $lockoutManager->isIpLocked( $request->ip() ) ) {
abort(429, 'Too many failed attempts from this IP');
}
$activeLockout = $lockoutManager->getUserLockout( $user ); // ?AccountLockout
Middleware
check.lockout aborts 403 for locked users and 429 for locked IPs:
Route::middleware(['auth', 'check.lockout'])->group(function (): void {
// gated routes
});
Lockout history
Each lock writes an AccountLockout row. Query it directly:
use ArtisanPackUI\SecurityAuth\Models\AccountLockout;
AccountLockout::where('user_id', $user->id)
->orderByDesc('created_at')
->paginate();
The AccountLockoutStatus Livewire component surfaces this on the user's account page.
CLI
php artisan security:lockout list
php artisan security:lockout list --user=user@example.com
php artisan security:lockout lock --user=user@example.com --duration=60 --reason="..."
php artisan security:lockout unlock --user=user@example.com
php artisan security:lockout clear-attempts --user=user@example.com
Events
AccountLocked fires when a lock is applied. Subscribe to alert / notify:
use ArtisanPackUI\SecurityAuth\Events\AccountLocked;
Event::listen( AccountLocked::class, function ( AccountLocked $event ): void {
Notification::send( $event->user, new AccountLockedNotification( $event->lockout ) );
} );