Override laravel 4's authentication methods to use custom hasing function

laravel extend vendor class
laravel 4.2 auth login
laravel facades
laravel 4 auth
laravel 6
laravel documentation
laravel interface
laravel 4 encrypt

I have a table in my database with users. Their password are generated with my own custom hashing function.

How do i override the Authentication methods in laravel 4 to use my own hash class?

This is what I have been trying to do:

    class CustomUserProvider implements Illuminate\Auth\UserProviderInterface {


    public function retrieveByID($identifier)
    {
        return $this->createModel()->newQuery()->find($identifier);
    }

    public function retrieveByCredentials(array $credentials)
    {
        // First we will add each credential element to the query as a where clause.
        // Then we can execute the query and, if we found a user, return it in a
        // Eloquent User "model" that will be utilized by the Guard instances.
        $query = $this->createModel()->newQuery();

        foreach ($credentials as $key => $value)
        {
            if ( ! str_contains($key, 'password')) $query->where($key, $value);
        }

        return $query->first();
    }

    public function validateCredentials(Illuminate\Auth\UserInterface $user, array $credentials)
    {
        $plain = $credentials['password'];

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

}

class CodeIgniter extends Illuminate\Auth\Guard {


}

App::bind('Illuminate\Auth\UserProviderInterface', 'CustomUserProvider');



Auth::extend('codeigniter', function()
{
    return new CodeIgniter( App::make('CustomUserProvider'), App::make('session'));
});

When I run the Auth::attempt method I get this error: ErrorException: Warning: Illegal offset type in isset or empty in G:\Dropbox\Workspaces\www\video\vendor\laravel\framework\src\Illuminate\Foundation\Application.php line 352

This is how ended up solving the problem:

libraries\CustomHasherServiceProvider.php

use Illuminate\Support\ServiceProvider;

class CustomHasherServiceProvider extends ServiceProvider {

    public function register()
    {
        $this->app->bind('hash', function()
        {
            return new CustomHasher;
        });
    }

}

libraries\CustomHasher.php

class CustomHasher implements Illuminate\Hashing\HasherInterface {

private $NUMBER_OF_ROUNDS = '$5$rounds=7331$';


public function make($value, array $options = array())
{

    $salt = uniqid();
    $hash = crypt($password, $this->NUMBER_OF_ROUNDS . $salt);
    return substr($hash, 15);
}

public function check($value, $hashedValue, array $options = array())
{
    return $this->NUMBER_OF_ROUNDS . $hashedValue === crypt($value, $this->NUMBER_OF_ROUNDS . $hashedValue);
}

}

And then I replaced 'Illuminate\Hashing\HashServiceProvider' with 'CustomHasherServiceProvider' in the providers array in app/config/app.php

and added "app/libraries" to autoload classmap in composer.json

Extending The Framework - Laravel, You can easily extend and override this class within your own application by overriding this binding. For example: <?php namespace App\Providers; class  Edit: This article was written around the time of Laravel 5.2. Sometime around the release of Laravel 5.3, this method got renamed to login(). Please bear that in mind and check the comments for

@vFragosop was on the right path with extending Auth.

There are a couple of ways to skin the cat and here is how I would do that without replacing the default Hasher class:

Include in your app/routes.php or wherever:

use Illuminate\Auth\Guard;
Auth::extend("eloquent", function() {
    return new Guard(
        new \Illuminate\Auth\EloquentUserProvider(new CustomHasher(), "User"),  
        App::make('session.store')
    );
});

Create and autoload a CustomHasher class (i.e., app/libraries/CustomHasher.php):

class CustomHasher extends Illuminate\Hashing\BcryptHasher {
    public function make($value, array $options = array())
    {
        ...
    }
    public function check($value, $hashedValue, array $options = array())
    {
        ...
    }
}

That's it.

Eloquent ORM - Laravel, Note: Eloquent will also assume that each table has a primary key column named id . You may define a primaryKey property to override this convention. The most concise screencasts for the working developer, updated daily. There's no shortage of content at Laracasts. In fact, you could watch nonstop for days upon days, and still not see everything!

Warning: I can't ensure this is works out of the box and there may be a few gotchas here and there. Keep in mind Laravel 4 is still on development. Wish I could provide a more precise answer, but codebase is still going through many changes and not everything is properly documented. Anyway, you are looking for something like this:

// on config/auth.php
'driver' => 'custom'
// on start/global.php
Auth::extend('custom', function() {
    // CustomUserProvider is your custom driver and should
    // implement Illuminate\Auth\UserProviderInterface;
    return new Guard(new CustomUserProvider, App::make('session'));
});

If this doesn't give you enough information to start, you should be able to figure it out by taking a look at those classes below:

EloquentUserProvider and DatabaseUserProvider These classes are the currently supported authentication drivers. They should guide you on how to create your CustomUserProvider (or any name you like really).

Manager This is the base class for anything that accepts custom drivers (including the AuthManager). It provides the methods for registering them like you do in Laravel 3.

Localization - Laravel, Consider upgrading your project to Laravel 7.x. Localization. Introduction; Language Files; Basic Usage; Pluralization; Validation Localization; Overriding Package  I am unsure about how Laravel loads it's routes. Could anyone help me to know how Laravel loads the same route? Does the first route load first or last routes override the first one? I thought the first route loads is preferred and won't be overrided, to override we need to load the route first. Could anyone correct if i am incorrect? Thanks

This was the top result on Google, but these answers are insufficient for anyone on Laravel 5. Even the documentation doesn't suffice.

I've successfully replaced the Hasher for only the UserProvider. The rest of my application continues to use the very nice BcryptHasher, while user authentication uses a custom hasher. To do this, I had to study these answers, the documentation, and Laravel's source code itself. Here's what I found. Hopefully I can save someone else's full head of hair. Feel free to crosspost this to a question about Laravel 5.


First, create your custom hasher, if you haven't already. Place it wherever you'd like.

class MyCustomHasher implements Hasher {

    public function make($value, array $options = []) {
        return md5( $value );  // PLEASE DON'T USE MD5!
    }

    public function check($value, $hashedValue, array $options = []) {
        if (strlen($hashedValue) === 0) {
            return false;
        }
        return $hashedValue === $this->make($value);
    }

    public function needsRehash($hashedValue, array $options = []) {
        return false;
    }

}

Edit any registered ServiceProvider as follows...

class AppServiceProvider extends ServiceProvider {

    public function boot() {
        Auth::provider('eloquentCustom', function ($app, $config) {
            return new EloquentUserProvider(new MyCustomHasher(), $config['model']);
        });
    }

}

You can replace 'eloquentCustom' with whatever you'd prefer.


Finally, edit your config/auth.php to use your custom provider. Here are the relevant parts...

return [

    // ...

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        // ...
    ],

    // ...

    'providers' => [
        'users' => [
            'driver' => 'eloquentCustom',  // <--- This is the only change
            'model' => App\User::class,
        ],
        // ...
    ],

    // ...

];


Here's a little explanation, because I can't believe how obscure this was.

As you may expect, authentication is configured with config/auth.php. There are two key parts: Guards and Providers. I haven't yet bothered to learn exactly what guards do, but they seem to enforce authentication requirements. Providers are responsible for providing the necessary information to the guards. Therefore, a Guard requires a Provider. You can see that, in the default configuration, guards.web.provider is mapped to providers.users.

Laravel provides two implementations of UserProvider by default: EloquentUserProvider and DatabaseUserProvider. These correspond to the two possible values for providers.users.driver: eloquent and database, respectively. Normally, the eloquent option is chosen. EloquentUserProvider needs a Hasher, so Laravel gives it whatever the standard implementation is (ie. BcryptHasher). We override this behavior by creating our own "driver" for instantiating the Provider.

Auth is our friendly neighborhood facade. It is backed by the AuthManager. The often suggested Auth::extend() method expects a Guard (contrary to what the documentation might suggest). We have no need to mess with the Guard. Instead, we can use Auth::provider() which basically does the same thing as extend(), except it expects a Provider. So we provide a function to create our own instance of a EloquentUserProvider, giving it our custom Hasher (eg. MyCustomHasher). We also include a driver "name" that can be used in the config file.

Now back to the config file. That driver name that we just created is now a valid value for providers.users.driver. Set it there and you're good to go!

I hope this all makes sense and is useful for someone!

Extending the Request and Response class in Laravel 4, There has been some confusion about how to extend the Illuminate Request and/​or the Response classes. Because of their importance in handling HTTP  Laravel provides several different approaches to validate your application's incoming data. By default, Laravel's base controller class uses a ValidatesRequests trait which provides a convenient method to validate incoming HTTP requests with a variety of powerful validation rules.

Laravel 5 auth override, For Laravel 4 I had done this using 2 different methods: overriding the default auth using AuthUserProvider & creating a custom auth facade. I leaned more to the  The Eloquent ORM included with Laravel provides a beautiful, simple ActiveRecord implementation for working with your database. Each database table has a corresponding "Model" which is used to interact with that table. Models allow you to query for data in your tables, as well as insert new records into the table.

Laravel: Extend (almost) any class - Italo Baeza Cabrera, It's been around since Laravel 4.2, so it's not something new. If you need to override a method, you're f*cked: extend the class and do what  By default, Laravel includes a User class in the app directory which implements this interface, so you may consult this class for an implementation example. Events. Laravel raises a variety of events during the authentication process. You may attach listeners to these events in your EventServiceProvider:

Overriding Laravel authentication controllers, They were written a long time ago in the early Laravel 4 days (and originally ran on the now-defunct Sentry package). It was time to bring them  Laravel aims to make implementing authentication very simple. In fact, almost everything is configured for you out of the box. The authentication configuration file is located at app/config/auth.php , which contains several well documented options for tweaking the behavior of the authentication facilities.

Comments
  • I'm glad to see the links helped you achieve your goal somehow. I hope this "adventure" gives you some insights about the framework. You should mark you answer as accepted to help others that come across it. :)
  • Great solution, but to get it to work I needed to implement the needsRehash() function too, not sure if it's even being used, I just returned true...
  • did you literally just put 'CustomHasherServiceProvider' in the providers array? I'm getting - Class 'CustomHasherServiceProvider' not found
  • @HenryIng-Simmons yes, just make sure to run composer dump after creating the class
  • The issue with this solution is that it completely replaces the "Hash" facade for the entire application, not just user authentication. So that might be a problem other code also uses Hash but you only want to change it for user authentication. See the other answers for solutions that only apply to user authentication specifically.
  • This sounded ideal, since the Hasher wouldn't be replaced app-wide. However, this is not working so far. EloquentUserProvider::validateCredentials() still sees a BcryptHasher. I'm calling the extend method from a ServiceProvider::boot(). Any ideas?
  • Never mind. I solved this and added my own answer here: stackoverflow.com/a/54299929/839455
  • I can't get this to work. I have updated my last attempt in the question
  • I suppose the App::bind is causing this, can't really understand what is going on it. You also don't need to extend the Guard class, you can simply use it. I'll update my sample code with that.
  • I fixed the error in the bind method and it is actually running the retrieveByCredentials function now. I'll try to see if I can make it work and let you know
  • Those are nice news, if you just want to change the hash, you could extend EloquentUserProvider and just override the validateCredentials.
  • I see, but an even better solution would be to only change the hashing class that the Auth use. Since that is the only thing i actually need to change, but not sure how to about only doing that