Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Login Throttle Bundle Laravel Package

nowo-tech/login-throttle-bundle

Symfony bundle that throttles login attempts to defend against brute-force attacks. Configure failed-attempt limits, lockout windows, and custom responses, with seamless integration into Symfony Security for safer authentication.

View on GitHub
Deep Wiki
Context7

Getting Started

First, a reality check. nowo-tech/login-throttle-bundle is a Symfony bundle (symfony/framework-bundle + symfony/security-bundle, registered via config/bundles.php), not a Laravel package. You cannot composer require it into a Laravel app and expect anything to boot: there is no ServiceProvider, no config/app.php entry, no publishable config, and Laravel's package discovery has nothing to discover. The value for a Laravel developer is either (a) you are actually working in a Symfony codebase and need login throttling, or (b) you want to copy its defaults into Laravel's own RateLimiter. Be explicit about which one you're doing before you install anything.

If you are on Symfony, minimal path:

composer require nowo-tech/login-throttle-bundle
  1. Confirm registration in config/bundles.php (Flex may have added it).
  2. Read README.md first, then the two files that define everything that matters: src/DependencyInjection/LoginThrottleExtension.php and src/DependencyInjection/Configuration.php. Those tell you the real config keys and whether the bundle writes security.firewalls.*.login_throttling for you or just ships a recipe/config snippet.
  3. Check config/packages/security.yaml — the bundle's whole job is producing something equivalent to Symfony's native:
security:
    firewalls:
        main:
            login_throttling:
                max_attempts: 5
                interval: '15 minutes'
  1. First use case worth implementing: cap failed form-login attempts per username + IP at 5 per 15 minutes, return HTTP 429 with Retry-After, and keep the login form message generic.

For the Laravel baseline you are probably comparing against, the equivalent is ~15 lines and requires no third-party package:

// AppServiceProvider::boot()
RateLimiter::for('login', fn (Request $r) => Limit::perMinutes(15, 5)
    ->by(Str::lower($r->input('email')).'|'.$r->ip()));

// LoginRequest
if (RateLimiter::tooManyAttempts($key = 'login:'.$this->throttleKey(), 5)) {
    throw ValidationException::withMessages(['email' => __('auth.throttle',
        ['seconds' => RateLimiter::availableIn($key)])]);
}

Implementation Patterns

Per-firewall scoping is the unit of configuration. Symfony applies login_throttling per firewall, so the real pattern is one block per entry point you expose — main (form login), admin (separate admin form), and not your stateless API firewall unless it has a login authenticator. In Laravel terms: one named RateLimiter::for() per guard/route group, not one global limiter.

Delegate storage to a shared backend once you have more than one app server. The counters live in a cache pool. On a single box the default is fine; behind a load balancer or in a rolling-deploy environment, per-host counters mean an attacker gets 5 × N attempts. Prefer defining an explicit limiter and pointing the throttle at it so the storage is Redis/cache.app shared:

framework:
    rate_limiter:
        login_limiter:
            policy: 'fixed_window'
            limit: 5
            interval: '15 minutes'
security:
    firewalls:
        main:
            login_throttling:
                limiter: login_limiter

This mirrors Laravel's Cache::store('redis') choice for RateLimiter — same reasoning, same failure mode if you skip it.

Layer it, don't replace it. Login throttling is one layer. Keep password-reset and 2FA-verification throttles separate (Laravel: RateLimiter::for('passwords'); Symfony: a second limiter on those controllers). Sharing one bucket lets an attacker burn your login budget to lock out a victim.

Hook the security events for observability. LoginFailureEvent / LoginSuccessEvent (or Laravel's Illuminate\Auth\Events\Lockout + Failed) are where you log lockouts and clear counters on success. Native Symfony throttling already clears on successful auth; your job is the telemetry, because a silent 429 storm is indistinguishable from an outage.

Integration tip: if you have custom authenticators (API key, magic link, SSO callback), login_throttling does not cover them. Apply the same limiter manually in the authenticator's authenticate() or in a kernel listener — the analogous Laravel move is calling RateLimiter::hit() inside your custom guard rather than assuming throttle: middleware reached it.

Testing pattern: functional test that posts bad credentials max_attempts + 1 times and asserts the final response is 429 with a Retry-After header. One focused test next to the existing login test is enough; do not build a throttling test suite for a config wrapper.

Gotchas and Tips

  • Vendor risk is the headline. 0 stars, 0 dependents, single maintainer, and a release date that reads oddly far in the future (2026-10-23) — treat the release metadata as unverified. Pin an exact version, commit composer.lock, and read the DI extension before trusting it in production. If it's genuinely 200 lines of YAML sugar, copying that YAML into your own security.yaml removes the dependency entirely and is the sanest option for a Laravel-minded dev.
  • login_throttling only guards the form-login authenticator. JSON login on the same firewall is covered; custom authenticators, remember-me re-auth, impersonation, and password reset are not. Verify with a test rather than assuming.
  • Proxies break the key. The throttle key includes the client IP. Without correctly configured trusted_proxies behind a load balancer, every request looks like the balancer's IP and one attacker locks out everybody. Same trap as $request->ip() returning 127.0.0.1 in Laravel when TrustProxies is wrong.
  • interval is a string duration ('15 minutes', '1 hour'), not seconds. A bare integer silently means something else — check Configuration.php for the accepted type rather than guessing.
  • Test flakiness. Counters persist in cache between test cases. Clear the pool (or use an array/null cache pool in config/packages/test/) or your second run of the same test starts already locked out. This is the single most common "why is CI red" cause with throttling.
  • 429 vs 401 semantics. Throttling must not leak whether an account exists. Key by username + IP (the default) rather than username alone, so unknown users and real users behave identically; also avoid a distinct message like "account locked" that only ever appears for valid accounts.
  • Extension points, in order of usefulness: the referenced framework.rate_limiter definition (storage, policy, interval), LoginFailureEvent/LoginSuccessEvent listeners for logging and manual reset-style clearing, and — last resort — decorating the bundle's service. Nothing here warrants editing vendor/.
  • No database audit trail. If you need "show the admin every lockout for user X", this bundle (and native Symfony throttling, and Laravel's RateLimiter) will not give it. Persist lockout events yourself from a listener/event subscriber.
  • Watch the deprecation claim. The README positions it as a replacement for anyx/login-gate-bundle. If you are migrating, diff the behaviour (key composition, lockout duration, reset-on-success) rather than swapping the dependency and assuming parity; write one test per behaviour you care about during the migration and delete the extras afterwards.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package