graham-campbell/passwd
A Laravel password validator and generator that checks strength, requires letters, numbers, and symbols, rejects common or weak passwords, and generates secure random passwords via a simple, configurable service provider integration.
password_hash/password_verify and, within Laravel, the Hash facade. There is no capability gap to fund and no roadmap item that gets unblocked by adopting it. The decision it does surface is a policy one: what is our default posture toward security-adjacent dependencies that are pre-1.0, archived, and have zero dependents? This package is a clean worked example for answering that question once, in writing.legacy_hash flag set at import, and dead code removed when the flag clears. That decision outlives whichever library implements it.Consider it only when all of the following hold:
password_* functions and the Hash facade don't already cover the multi-format verify case.0.4.0-alpha tag with composer.lock committed. Never a caret range on a pre-1.0 security-adjacent package; alpha tags move.hash/check boundary, one container binding) so the blast radius of abandonment is a single class.defined('PASSWORD_ARGON2I') before making Argon2 the default — it's a compile-time dependency, and it was frequently absent on stock builds of that era. Discovering this on the signup path is the worst possible failure mode.Look elsewhere when:
Hash facade — vendor-maintained, already installed, and wrapped around the same primitives.GrahamDeprecated namespace; there will be no CVE patches and no PHP-version compatibility work. Adopting it means you own the fork whether or not you say so.Hash facade plus a small custom checker for the one legacy format gets you the entire migration benefit with none of the dependency.One config caveat worth putting in the decision record: if you need two hashers live at once (current writes vs. legacy verifies), do not fight the published config — the facade doesn't cleanly override per call. Bind your own instances and call the checker chain explicitly. That's roughly fifty lines, and noticing you had to write them is itself a data point about whether the dependency is pulling its weight.
For executives — one short paragraph. This is not a feature investment and it should not appear on a roadmap as one. The package is a small wrapper around password functions PHP already ships, published under a deprecated namespace with no dependents and no future security patches. The only business decision it informs is a real one: when we absorb users from a legacy system, do we migrate their existing passwords or force a reset? Migrating is usually cheaper in churn and support load, and this library handles that narrow case well enough to be worth a time-boxed spike. Everything else about it is a risk-register entry, not a build. If we adopt it, we adopt it behind our own interface, pinned to an exact version, with a written plan to remove it — and with a named owner for that plan.
For engineering — the working summary. Treat it as a migration utility with an expiry date, not an auth dependency. Pin 0.4.0-alpha, commit the lockfile, and wrap it in a one-class adapter so nothing in the application ever touches the Passwd facade directly. The whole exit plan is a paragraph: swap the adapter body to password_hash($plain, PASSWORD_BCRYPT, ['cost' => N]) and password_verify($plain, $hash). If you can't articulate that swap cleanly, you've coupled harder than the package deserves. Use the hasher/checker split for verify-any-then-rehash-on-success, gate the legacy checkers behind a legacy_hash flag set at import time so you're not running three formats on every login, and verify the plaintext before you hash and persist — and make sure the save doesn't re-trigger your setPasswordAttribute mutator into a hash-of-a-hash. Keep one real integration test that round-trips an actual hash; a stubbed binding proves your controller logic, not that credentials work. Add password to $hidden on every model that carries one, and never compare hashes with == or let them into logs and API payloads. Finally, and most importantly: if the real constraint is that we're still on a Laravel 4.1-era stack, say so out loud. That's the ticket, and this package is a footnote to it.
How can I help you explore Laravel packages today?