Weave Code
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

Symfony Password Exposed Bundle Laravel Package

divineomega/symfony-password-exposed-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require jord-jd/symfony-password-exposed-bundle
    

    Ensure DivineOmega\PasswordExposedBundle\DivineOmegaPasswordExposedBundle::class is registered in config/bundles.php.

  2. Enable in Config: Add to config/packages/divineomega_password_exposed.yaml:

    password_exposed:
        enable: true
    
  3. First Use Case: Inject the PasswordExposedCheckerInterface into a controller/service and call isExposed():

    use JordJD\PasswordExposed\Interfaces\PasswordExposedCheckerInterface;
    
    public function checkPassword(PasswordExposedCheckerInterface $checker): bool
    {
        return $checker->isExposed('user_password_here');
    }
    

Where to Look First

  • Bundle Docs: README for config and usage.
  • Underlying Library: jord-jd/password_exposed for API details (e.g., rate limits, hash prefixes).
  • Symfony Cache: Check cache.app (default) for cached responses.

Implementation Patterns

Core Workflows

  1. Password Validation in Registration/Login:

    public function register(Request $request, PasswordExposedCheckerInterface $checker)
    {
        $password = $request->request->get('password');
        if ($checker->isExposed($password)) {
            throw new \RuntimeException('Password exposed in a breach. Choose another.');
        }
        // Proceed with registration...
    }
    
  2. Bulk Checks (e.g., Password Reset): Use a loop with error handling for rate limits:

    foreach ($userPasswords as $password) {
        try {
            $isExposed = $checker->isExposed($password);
            $results[$password] = $isExposed;
        } catch (RateLimitExceededException $e) {
            // Retry or log
        }
    }
    
  3. Custom HTTP Client: Override the default client for proxies/debugging:

    password_exposed:
        http_client: symfony.http_client
    

Integration Tips

  • Event Listeners: Trigger password checks during UserPasswordHasher events.
  • Form Validation: Add a custom constraint:
    use JordJD\PasswordExposed\Validator\Constraints\PasswordExposed;
    
    #[PasswordExposed]
    private $password;
    
  • Async Checks: Use Symfony Messenger for non-blocking validation.

Gotchas and Tips

Pitfalls

  1. Rate Limits:

    • The API enforces 5 requests/second. Cache responses aggressively (cache_lifetime: 2592000 = 30 days).
    • Handle RateLimitExceededException gracefully (e.g., queue retries).
  2. Hash Prefixes:

    • The API requires first 5 chars of SHA-1 hash of the password. The bundle handles this internally, but debug with:
      $hashPrefix = substr(sha1('password'), 0, 5); // e.g., "5baa6"
      
  3. Case Sensitivity:

    • The API is case-insensitive, but test edge cases (e.g., "Passw0rd" vs "passw0rd").
  4. False Positives:

    • Common passwords (e.g., "123456") may appear in breach data. Combine with other checks (e.g., zxcvbn complexity).

Debugging

  • Enable Logging:

    password_exposed:
        enable: true
    

    Check Symfony logs for API responses/errors.

  • Disable in Dev:

    password_exposed:
        enable: "%kernel.debug%" # Disables in dev mode
    

Extension Points

  1. Custom Cache: Override cache.app to use Redis/Memcached for high traffic:

    password_exposed:
        cache: cache.redis
    
  2. Mock API for Tests: Use a custom HttpClient to mock responses:

    $client = new MockHttpClient([
        new Response(200, [], '{"Count":0}')
    ]);
    $container->set('password_exposed.http_client', $client);
    
  3. Extend Checker: Implement PasswordExposedCheckerInterface to add local breach checks:

    class CustomChecker implements PasswordExposedCheckerInterface {
        public function isExposed(string $password): bool {
            return $this->apiChecker->isExposed($password) || $this->localCheck($password);
        }
    }
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope