Passwords should never be encrypted (reversible) — they should be hashed (one-way). Laravel's Hash facade defaults to bcrypt, with argon2id available as a configurable alternative, and both are designed so the plaintext password can never be recovered from the stored hash, only verified against it.
Hashing a password
use Illuminate\Support\Facades\Hash;
$hashed = Hash::make($request->password);
With Eloquent's hashed cast (Laravel 10+), this happens automatically whenever the attribute is set — no manual Hash::make() call needed in the controller:
protected function casts(): array
{
return [
'password' => 'hashed',
];
}
Why the same password produces a different hash every time
Both bcrypt and argon2 include a random salt baked into the output string itself, so hashing "password123" twice produces two different-looking hashes — this is intentional and prevents identical passwords from producing identical hashes across different user rows (which would otherwise leak who shares a password).
Verifying a login — never re-hash and compare strings
if (Hash::check($request->password, $user->password)) {
// correct password
}
Hash::check() re-derives the hash using the same salt embedded in the stored value and compares in constant time — this is the only correct way to verify a password. Comparing Hash::make($input) === $storedHash directly will fail even for the correct password, because a fresh Hash::make() call generates a new random salt each time.
Checking if a hash needs rehashing
If you ever change the hashing algorithm or cost factor in config/hashing.php, existing stored hashes stay valid (Laravel identifies the algorithm from the hash's own prefix) but won't benefit from the new setting until rehashed:
if (Hash::needsRehash($user->password)) {
$user->update(['password' => $request->password]); // rehashes under the hashed cast
}
This is typically checked once, right after a successful login (you already have the plaintext password at that moment) — never proactively against stored hashes, since you can't rehash a password you don't have in plaintext.