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

Laravel Nist Password Rules Laravel Package

langleyfoxall/laravel-nist-password-rules

Laravel validation rules implementing NIST SP 800-63B password guidance: enforce minimum length, reject breached and common dictionary passwords, block context-specific words, and avoid outdated composition rules. Easy to add to form requests and validators.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require langleyfoxall/laravel-nist-password-rules:^8.2. v8.x targets modern Laravel/PHP; check the composer.json constraints before dropping it into an older app.
  • Laravel package auto-discovery handles registration — there is no service provider to add to config/app.php on Laravel 5.5+.
  • Look first at src/PasswordRules.php. That single static helper class is the whole public API surface for most projects; the individual rule classes live under src/Rules/ and are what the helper returns.
  • The first use case is almost always a registration form. Replace hand-rolled min:8|confirmed|regex:... rules with the package's bundle:
use LangleyFoxall\LaravelNISTPasswordRules\PasswordRules;

$request->validate([
    'password' => PasswordRules::register(8),
]);
  • The array the helper returns is a normal Laravel rule array, so it composes with confirmed, required, and max: without any glue code:
'password' => array_merge(['required', 'confirmed', 'max:255'], PasswordRules::register(8)),
  • About v8.2.0: the release notes are a version bump only ("Bumping versions", single PR). There are no new rules, no signature changes, and no deprecations. There is no migration work — just let Composer float you to ^8.2. The rest of this assessment is the initial baseline for the package as a whole.

Implementation Patterns

Pick the right helper for the flow. Registration and password-change have different requirements (change usually needs a username/email block and reuse prevention), and the package exposes separate helpers rather than one overloaded method:

// Account creation
'password' => PasswordRules::register(8),

// Password reset / change
'password' => PasswordRules::changePassword($user->email, 8),

The *WithContext variants additionally reject passwords containing the username/email or other context values. Use them anywhere an identity is already known — registration with an email field, invite acceptance, admin-created users:

'password' => PasswordRules::registerWithContext($request->email, 8),
'password' => PasswordRules::changePasswordWithContext($user->email, 8),

Put the rules in Form Requests, not controllers. These rule sets are long enough that inline validation gets noisy, and Form Requests give you one place to swap register for changePassword and to keep the authorize() logic next to it.

Use the rule objects directly when you need surgical control. The helper is a convenience bundle; each check is a standalone Illuminate\Contracts\Validation\Rule. If you only want the HaveIBeenPwned check without the dictionary/common-password checks, instantiate the individual rule classes from src/Rules/ and mix them with Laravel's native Password::min(). This is also the escape hatch when a bundle is too strict for a legacy system you're tightening incrementally.

Align with Password::defaults() deliberately. Laravel's own password builder and this package overlap on length and on rejecting compromised passwords. Pick one as the source of truth — typically this package for the NIST-specific checks, plus Password::defaults() only for uncompromised() if you don't want the bundled list. Running both is harmless but doubles validation messages and outbound HTTP calls.

Fortify / Breeze / Jetstream. These publish their own PasswordValidationRules trait or CreateNewUser action. Replace the Password::min(8) return value with PasswordRules::register(8) there — that is the single integration point in most apps, and it means every entry path (register, reset, update) gets consistent checks.

Testing. The compromised-password rule makes an outbound HTTP call. Wrap feature tests that hit it with Http::fake() and a canned range response, or set the test environment to skip the network check. Without this, your CI suite gets slow and flaky the moment the API hiccups.

Http::fake(['api.pwnedpasswords.com/*' => Http::response("0018A45C4D1DEF81644B54AB7F969B88D65:1\r\n", 200)]);

Localization. Validation messages ship with the package. If your app is not English, publish the package's language files (php artisan vendor:publish --tag=..., confirm the exact tag in the README) and translate them rather than overriding messages ad hoc at each call site.

Gotchas and Tips

  • The network call is the #1 source of surprises. The compromised-password check queries the HIBP range API. In air-gapped environments, behind strict egress rules, or on slow CI it will time out and fail validation with a confusing message. Confirm the failure mode and consider caching range responses, or reserve that rule for production only.
  • Do not pair this with composition rules. NIST SP 800-63B explicitly discourages forced mixed case, symbols, and periodic rotation. If you keep regex:/[A-Z]/ and different:old_password-style rotation alongside this package, you have negated the reason you installed it. Audit the surrounding rules when you adopt it.
  • Set max generously. A common mistake is max:20 inherited from an old form. NIST says accept long passphrases; allow at least 64 (255 is a safe ceiling) and only reject on server-side limits you actually enforce in the column.
  • changePassword does not enforce reuse history. The package checks quality, not whether the user already used that password. If you need "not one of your last N", implement it yourself against a password history table — don't assume the helper covers it.
  • Truncation and encoding. NIST guidance is to hash the full password, not a truncated version. If your password_hash column or a legacy bcrypt call truncates at 72 bytes, a long passphrase is silently weakened. Ensure the max rule and the column length agree with your hashing strategy.
  • The bundled common/dictionary lists are finite. They catch the obvious offenders cheaply, but they are not a substitute for the breach check. Expect false negatives on niche or recently leaked passwords.
  • Rule arrays are opaque in stack traces. When validation fails and you can't tell which rule fired, dd(PasswordRules::register(8)) in a Tinker session to see the concrete array. It's usually an ordering or a stray string rule, not the package.
  • Extension point: the individual rule classes are small and swappable. If you need to point the common-password check at your own corpus, or add a check for company-name tokens, writing a parallel Rule implementation and appending it to the returned array is cleaner than forking the package.
  • Version bump releases are the norm here. v8.2.0 is a dependency refresh with no API delta, which means patch/minor bumps are low-risk — but still pin ^8.2 rather than * so a future major doesn't land unreviewed in a deploy.
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.
skyraptor/chatter
edlugz/sasapay
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