kevin-chappo's avatar

help extending bcrypthasher

I began with this starter package - https://github.com/krisanalfa/lumen-jwt

I am creating an API for an existing user base where I had passwords stored with separate hashes. After searching around I believe I found the correct way to resolve this with a transitional hash check and update solution by creating my own service provider that calls my own hashing class, that class extends the default bcrypthasher class and replaces the check method with my own transitional check method. I registered the service in the bootstrapp/app.php file.

Here is the problem, when I post to auth/login my check function does not run, the one from the bcrypthasher class still runs. Even though upon debugging I can see the correct class exists in the service container bound to "hash". What am I missing?

bootstrap/app.php // Custom transitional hasher $app->register(App\Providers\TransitionalHashServiceProvider::class);

Service Provider class HashServiceProvider 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 BcryptHasher;
    });
}

/**
 * Get the services provided by the provider.
 *
 * @return array
 */
public function provides()
{
    return ['hash'];
}

}

New class TransitionalHasher extends \Illuminate\Hashing\BcryptHasher {

public function check($value, $hashedValue, array $options = array())
{
    die('this never runs!');
    // If check fails, is it a hash from a previous version?
    if ( !password_verify($value, $hashedValue) )
    {
        // Attempt to match user using previous version hash check
        // $user = foo;

        if ($user)  // We found a user with a matching hash
        {
            // Update the password to Laravel's Bcrypt hash
            $user->password = Hash::make($value);
            $user->save();

            // Log in the user
            return true;
        }
    }

    return password_verify($value, $hashedValue);
}

}

0 likes
3 replies
JackJones's avatar

Your service provider loads a new instance of the old bcrypt hasher though:

public function register()
{
    $this->app->singleton('hash', function () {
        return new BcryptHasher;
    });
}
kevin-chappo's avatar

I pasted the original service provider and not my own by mistake - mine is below sorry

class TransitionalHashServiceProvider 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 TransitionalHasher;
    });
}

/**
 * Get the services provided by the provider.
 *
 * @return array
 */
public function provides()
{
    return ['hash'];
}

}

JackJones's avatar

I'm not 100% as I'm only a beginner, but I'd imagine after the application has been bootstrapped you would bind your class:

public function boot()
{
    $this->app->bind('hash', TransitionalHasher::class);
}

If you are implementing a Contract then you may be better off binding to that

Please or to participate in this conversation.