Kai
Kai

Reputation: 21

Manually hashing plaintext passwords in database always returns false with Hash::check

I am migrating a site into the laravel framework, and the database for the old site stores user passwords as plaintext. Obviously that's an issue, so I used this code to hash the passwords. The client has also requested that users be able to login through their username, so I edited the default login controller to account for that. Creating a new account and logging into it works just fine, but trying to login to an existing account always returns invalid credentials.

I started with php artisan make:auth and have edited the generated files from there.

I have tried hashing the passwords in a migration, as well as in php artisan tinker. I have also tried using $user->password = Hash::make($user->password); rather than $user->password = bcrypt($user->password);, also in migration and tinker. I've gotten the same result each time while trying to log in.

If I use Hash::make in artisan tinker and then Hash::check against the created hash and the plaintext password, it returns true, but when I attempt to login with those credentials, it fails. bcrypt returns false for Hash::check in tinker. Using bcrypt returns true for Hash::needsRehash while Hash::make returns false.

Usernames are set as unique.

User model:

protected $primaryKey = 'user_id';

protected $fillable = [
    'username', 'password',
];

protected $guarded = [];

protected $hidden = [
    'password', 'remember_token',
];

public function getAuthPassword()
{
    return $this->password;
}

LoginController:

use AuthenticatesUsers;
protected $redirectTo = '/home';
public function __construct()
{
    $this->middleware('guest')->except('logout');
}
public function username()
{
    return 'username';
}

login.blade username/password form fields:

<div class="form-group row">
    <label for="username" class="col-md-4 col-form-label text-md-right">{{ __('Username') }}</label>
    <div class="col-md-6">
        <input id="username" type="text" class="form-control @error('username') is-invalid @enderror" name="username" value="{{ old('username') }}" required autofocus>
            @error('username')
            <span class="invalid-feedback" role="alert">
                <strong>{{ $message }}</strong>
            </span>
            @enderror
    </div>
</div>
<div class="form-group row">
    <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
    <div class="col-md-6">
        <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
        @error('password')
        <span class="invalid-feedback" role="alert">
            <strong>{{ $message }}</strong>
        </span>
        @enderror
    </div>
</div>

I expect to be able to login to an existing account but when I attempt to (using a backup of the original database to check passwords), I receive a typical "These credentials do not match our records." error a user would receive from entering an incorrect password.

Upvotes: 0

Views: 320

Answers (1)

Kai
Kai

Reputation: 21

I figured out my issue. At some point, my password field length got changed to 20, rather than 250. Obviously this was truncating the hash. Whoops! Figured it was something silly that I'd missed.

Upvotes: 1

Related Questions