- How do I install ubient/laravel-pwned-passwords in a Laravel app?
- Install it with Composer using composer require ubient/laravel-pwned-passwords. Laravel's package auto-discovery registers the service provider, so no manual registration is normally needed. Publish the package config with the vendor:publish Artisan command so you can tune the breach threshold, cache settings and error message.
- Which Laravel and PHP versions does this package support?
- Version 3.4.0 added PHP 8 support as a minor, backward-compatible release within the 3.x line, so it should still run on previously supported PHP versions. In practice that means it pairs with Laravel releases that run on PHP 8.1 and above, such as Laravel 9 and 10. A generic PHP 8 claim does not prove 8.2 or 8.3 coverage, so check the composer.json constraints and the CI matrix before adopting it, since PHP 8.2 deprecates dynamic properties and other runtime behaviour changes can surface quietly.
- Is my user's password sent to Have I Been Pwned when the pwned rule runs?
- No. The rule hashes the password with SHA-1 on your own server and sends only the first five characters of that hash to the Pwned Passwords range API. The API returns every known hash suffix sharing that prefix, and the comparison against the full hash happens locally. This is the k-anonymity model, so neither the plaintext password nor the complete hash ever leaves your infrastructure.
- How do I add the pwned rule to a validator or FormRequest?
- Treat it like any other Laravel validation rule by adding the string pwned to the rules array. For example, in a FormRequest return 'password' => ['required', 'confirmed', 'pwned'] from the rules method. The rule runs alongside the built-in password rules such as min, letters and uncompromised, and it fails validation when the password appears in the breach corpus above your configured threshold.
- How do I change the breach threshold so only frequently breached passwords are rejected?
- Publish the package config file and adjust the threshold value; the rule counts how many times the hash appears in the Pwned Passwords corpus and only rejects once that count meets or exceeds the threshold. The default rejects any known breach, which is the strictest and usually the right choice for registration and password changes. Raising the threshold, for example to five, lets through passwords that have leaked only a handful of times, trading security for fewer support complaints.
- Does the package cache the API responses, and how is that configured?
- Yes, the package caches Pwned Passwords responses to cut down on outbound HTTP calls, which matters because a single prefix range can be several hundred kilobytes. The published config exposes the caching options, typically the cache store and the time to live, keyed by the five-character hash prefix. Because prefixes are shared across many passwords, a warm cache also makes validation noticeably faster during traffic spikes.
- How do I customise or translate the pwned validation error message?
- The rule ships with a translatable message, so you can publish the language files and edit the string, or add your own translation key in your app's lang directory. You can also override it per validator by passing a messages array to the Validator facade or by setting the message on the FormRequest. This keeps the user-facing copy consistent with the rest of your password policy wording.
- How can I test the pwned rule without hitting the real Have I Been Pwned API?
- Because the rule queries the range endpoint over HTTP, you can stub the response with Laravel's Http::fake() and return a canned range body containing the suffix you want to simulate. That lets you assert both the passing and failing paths deterministically in your test suite without network access. Remember to cover the threshold logic and the cached path as well, since those branches behave differently from a cold API call.
- Is it safe to run the pwned rule in production if the API is unreachable?
- The trade-off is explicit: if the range API cannot be reached, the rule cannot confirm whether the password is compromised, so you must decide whether validation should fail open or closed. Aggressive response caching reduces how often that situation arises, but you should still plan for latency and timeouts on the request path. Many teams fail open at login and fail closed at registration and password reset, where the user can retry without losing access.
- What are the alternatives to ubient/laravel-pwned-passwords?
- Laravel ships a built-in Password::uncompromised() rule that performs the same SHA-1 prefix check against Pwned Passwords using k-anonymity. This package remains useful if you want a configurable breach threshold, package-level response caching and a publishable translatable message out of the box. Whichever you pick, verify maintenance cadence and the supported Laravel and PHP matrix, since a one-line changelog on a minor release says little about long-term upkeep.