5
votes

I am trying to integrate the auth in laravel 5.4 within an existing database where the user and password fields have other names (memberid, passwordnew_enc). With the bellow changes and forcing the create function in RegisterController to use MD5 I managed to make the registration work. It also logins fine after registration. However the actual login form returns:

These credentials do not match our records.

So far I have changed the User.php

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

and

public function setPasswordAttribute($value)
{
    $this->attributes['password'] = md5($value);
}

Also on LoginController.php

public function username()
{
    return 'memberid';
}

Did I miss something ?

I only need to change the two column names to fit and the password encryption from bcrypt to md5

3
MD5 is not a sufficient hashing algorithm for passwords. You will be better off staying with the built in bcrypt hashing and requiring all your users to reset their password.patricus
If you read the question you'd understand why. I am well aware. I don't have access to the database and there is another system operating with those users which at this point can't be switched.dev
where does setPasswordAttribute() come from?upful
@dev There is nothing in your question that states you are aware of this, or gives a reason as to why you can't change your hashing algorithm. You only state that the current passwords are MD5 hashed, and that is the reason for your question. Since there was no indication within the question that you know MD5 is not appropriate, I wrote a comment to let you know, since a lot of developers do not know that.patricus
There always seems to be a reason that we can't have security, is it any wonder that hackers are taking over, that there is breach after breach? Well guess who creates all the flawed code? Developers. It really is necessary to push back as hard as possible, it is not just bad code, it is code putting the user's security at risk. We need to act as professionals if we expect to be treated as professionals.zaph

3 Answers

23
votes

I would make custom user provider php artisan make:provider CustomUserProvider:

<?php

namespace App\Providers;

use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;

class CustomUserProvider extends EloquentUserProvider {

    /**
    * Validate a user against the given credentials.
    *
    * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
    * @param  array  $credentials
    * @return bool
    */
    public function validateCredentials(UserContract $user, array $credentials)
    {
        $plain = $credentials['password']; // will depend on the name of the input on the login form
        $hashedValue = $user->getAuthPassword();

        if ($this->hasher->needsRehash($hashedValue) && $hashedValue === md5($plain)) {
            $user->passwordnew_enc = bcrypt($plain);
            $user->save();
        }

        return $this->hasher->check($plain, $user->getAuthPassword());
    }

}

This way if the password exists using md5 it will allow it to work once and then rehash it.


You will register the CustomUserProvider in App\Providers\AuthServiceProvider boot() as follows:

$this->app['auth']->provider('custom', function ($app, array $config) {
            $model = $app['config']['auth.providers.users.model'];
            return new CustomUserProvider($app['hash'], $model);
        });

Edit your config/auth.php

'providers' => [
        'users' => [
            'driver' => 'custom',
            'model' => App\User::class,
        ],
],

You will also need to add the following as mentioned previously...

app\Http\Controllers\Auth\LoginController.php

public function username()
{
    return 'memberid';
}

app\User.php

public function getAuthIdentifierName()
{
    return 'memberid';
}

public function getAuthIdentifier()
{
    return $this->memberid;
}

public function getAuthPassword()
{
    return $this->passwordnew_enc;
}
4
votes

Alright I got it

app\User.php

public function setPasswordAttribute($value)
{
    $this->attributes['password'] = md5($value);
}

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

public function getAuthIdentifierName()
{
    return 'memberid';
}

app\Http\Controllers\Auth\LoginController.php

public function username()
{
    return 'memb___id';
}

config\app.php

    // Illuminate\Hashing\HashServiceProvider::class,
    App\Providers\MD5HashServiceProvider::class,

app\Providers\MD5HashServiceProvider.php

<?php namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class MD5HashServiceProvider extends ServiceProvider
{
    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = true;
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('hash', function () {
            return new \MD5Hasher;
        });
    }
    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return ['hash'];
    }
}

lib\MD5Hasher\MD5Hasher.php

<?php
class MD5Hasher implements Illuminate\Contracts\Hashing\Hasher
{
    /**
     * Hash the given value.
     *
     * @param  string  $value
     * @return array   $options
     * @return string
     */
    public function make($value, array $options = array())
    {
        return md5($value); //hash('md5', $value);
    }
    /**
     * Check the given plain value against a hash.
     *
     * @param  string  $value
     * @param  string  $hashedValue
     * @param  array   $options
     * @return bool
     */
    public function check($value, $hashedValue, array $options = array())
    {
        return $this->make($value) === $hashedValue;
    }
    /**
     * Check if the given hash has been hashed using the given options.
     *
     * @param  string  $hashedValue
     * @param  array   $options
     * @return bool
     */
    public function needsRehash($hashedValue, array $options = array())
    {
        return false;
    }
}

composer.json

...
"autoload": {
    "classmap": [
        ...
        "app/Lib"
    ],
 ...
1
votes

upful's code worked for me (in Laravel 5.4)

But I needed to add:

use Illuminate\Contracts\Auth\Authenticatable as UserContract;

in the CustomUserProvider class.