- How do I replace Laravel’s Hash facade with symfony/password-hasher in my existing app?
- Bind the `PasswordHasherInterface` in your `AppServiceProvider` using the `PasswordHasherFactory` with your configured algorithms. Override `Hash::make()` and `Hash::check()` calls to use the factory’s hasher. Example: `$this->app->bind(PasswordHasherInterface::class, fn($app) => (new PasswordHasherFactory($app['config']['password-hasher']))->getPasswordHasher('default'));`
- Which algorithm should I use for Laravel 10+ applications—bcrypt, sodium, or Argon2id?
- Use **Argon2id** for high-security needs (e.g., admin accounts) due to its memory-hard nature, **bcrypt** for general use (balance of security/performance), and **sodium** if available (requires `ext/sodium`). Avoid SHA-1/MD5. Configure via `PasswordHasherFactory` with cost parameters tuned for your server.
- Can symfony/password-hasher detect and migrate legacy hashes (e.g., SHA-1) in my Laravel database?
- Yes. Use `getPasswordHasherForUser($hash)` to auto-detect the algorithm. Gradually rehash legacy hashes on login or during batch jobs. The package won’t break existing bcrypt/Argon2id hashes. Audit for weak hashes with `str_starts_with($hash, '$2y$')` or regex patterns.
- How does symfony/password-hasher integrate with Laravel Fortify or Passport for password resets/OAuth?
- Bind the factory to Fortify’s `hashPassword()` or Passport’s `hashClientSecret()` via Laravel’s service container. Example: `Fortify::hashPassword(fn($password) => $hasher->hash($password))`. No changes to Fortify/Passport logic are needed—just replace the underlying hasher.
- What are the performance implications of Argon2id vs. bcrypt in production Laravel APIs?
- Argon2id is **slower** (CPU/memory-intensive) than bcrypt but more resistant to brute force. Benchmark with `symfony/password-hasher`'s built-in tests. For APIs, cache hashes if stateless (e.g., JWT) or use bcrypt for guests/Argon2id for admins via the factory.
- Does symfony/password-hasher support Laravel’s `MustVerifyPassword` or `CanResetPassword` contracts?
- Yes. The package works seamlessly with Laravel’s auth contracts. Hash verification via `verify()` aligns with `MustVerifyPassword::verifyPassword()`, and password resets via `CanResetPassword` use the same hasher instance. No contract modifications are required.
- How do I handle Sodium availability issues in shared hosting environments?
- Configure a fallback algorithm in `PasswordHasherFactory`. Example: `['default' => ['algorithm' => 'bcrypt'], 'sodium_fallback' => ['algorithm' => 'bcrypt']]`. Use `try-catch` around `getPasswordHasher('sodium')` to gracefully fall back. Check `extension_loaded('sodium')` in a pre-flight check.
- Can I use symfony/password-hasher with Laravel 9.x, or is it Laravel 10+ only?
- It works with **Laravel 9.x** but requires minor polyfills for Symfony 6+ dependencies. For Laravel 8.x, use `symfony/password-hasher:^5.4` with a compatibility layer. Test with `phpunit` to ensure no breaking changes in the auth pipeline.
- What’s the best way to test symfony/password-hasher in Laravel’s authentication tests?
- Mock the `PasswordHasherInterface` in PHPUnit tests using `createMock(PasswordHasherInterface::class)`. Verify `hash()` returns consistent outputs and `verify()` behaves for correct/incorrect passwords. Test edge cases like empty strings or very long passwords.
- Are there alternatives to symfony/password-hasher for Laravel, and why should I choose this one?
- Alternatives include `laravel/breeze` (basic bcrypt) or `phpass` (legacy). Choose `symfony/password-hasher` for **algorithm flexibility**, **NIST/OWASP compliance**, and **Laravel-native integration**. It’s battle-tested in Symfony, supports modern algorithms, and avoids vendor lock-in with a simple API.