Forum

[Laravel 5] How do I create a custom auth in laravel 5

In laravel 4.2 there's this example how can I do the same thing in laravel 5.x?

adaojunior
adaojunior
  • 2 years ago

Check this article http://www.codeheaps.com/php-programming/laravel-5-new-auth-generators-user-authentication/

@pzotov I've seen that article before, I'm not sure if I'm missing something but what I want to do is create a custom UserProvider, as default we have EloquentUserProvider and DatabaseUserProvider and I already know how to create my custom UserProvider my I dont know how I set this provider for use just like:

Auth::extend('dummy', function($app)
{
    return new MyApp\Extensions\DummyAuthProvider;
});
usm4n
Solution

Hi, Let us do it step by step :)

  • 1 - Update the driver key inside config/auth.php like this:
    'driver' => 'custom', 
  • 2 - Create an Auth directory inside the app root (or in a place of your preference) and create the User Provider Interface implementation. I will name the file as CustomUserProvider.php:
<?php namespace App\Auth;

use Illuminate\Contracts\Auth\User as UserContract;
use Illuminate\Auth\UserProviderInterface;

class CustomUserProvider implements UserProviderInterface {

    protected $model;

    public function __construct(UserContract $model)
    {
        $this->model = $model;
    }

    public function retrieveById($identifier)
    {

    }

    public function retrieveByToken($identifier, $token)
    {

    }

    public function updateRememberToken(UserContract $user, $token)
    {

    }

    public function retrieveByCredentials(array $credentials)
    {

    }

    public function validateCredentials(UserContract $user, array $credentials)
    {

    }

}

Now implement the UserProviderInterface methods however you want.

  • 3 - Create a new Service Provider inside your app/Providers directory and name it according to the convention you are using. I will call it `CustomAuthProvider'.php. Now, in this file we will register the new auth drivers that we have specified inside the config file:
<?php namespace App\Providers;

use App\User;
use App\Auth\CustomUserProvider;
use Illuminate\Support\ServiceProvider;

class CustomAuthProvider extends ServiceProvider {

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->app['auth']->extend('custom',function()
        {
            return new CustomUserProvider(new User);
        });
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

}

Now in the last step add the name of the provider into the providers array of the config/app.php file.


'providers' => [ /* * Application Service Providers... */ 'App\Providers\EventServiceProvider', 'App\Providers\RouteServiceProvider', 'App\Providers\CustomAuthProvider', ......

I hope you will get it right this time. Regards!

@pzotov Thanks for sharing my article!

Thank you @usm4n, that's actually pretty simple, I'll try it tomorrow and I'll leave a comment here.

@usm4n works fine, thank you.

No problem :)!

Thank you so much usm4n! I was almost there but stuck on how to register my custom UserProvider!

hey usm4n. this is a big help with what i need as well. thank you very much for this. :)

Hi @usm4n - Thanks for the help.

I've followed your guidance, and as you can see below, my code matches yours, however, when I try to load the site, it gives me this error:

[InvalidArgumentException]      
Driver [custom] not supported.

From the stack trace it looks like the error is in AuthManager.php line 15, where it calls the createDriver() method. It appears its looking for a createCustomDriver() method (which obviously doesn't exist in authManager).

Did I miss something? Any input would be helpful... thanks!

@josh7weaver, sorry for being late to the party :).

The problem seems to be inside your boot method, the name of the driver is not the same i.e. you have specified the name as 'driver ' => 'custom' and then you are extending a different driver i.e. token. Either change the driver name inside your config file as token or use the name custom inside the boot method:

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->app['auth']->extend('custom', function ($app)
        {   

           $model = $app['config']['auth.model'];

           return new CustomUserProvider($app['hash'], new $model);
        });
    }

Please note the new operator, I have passed an instance of the Model which in my case is App\User. You will also need to change the constructor of your CustomUserProvider:


class CustomUserProvider implements UserProvider { /** * The hasher implementation. * * @var \Illuminate\Contracts\Hashing\Hasher */ protected $hasher; /** * The Eloquent user model. * * @var string */ protected $model; /** * Create a new database user provider. * * @param \Illuminate\Contracts\Hashing\Hasher $hasher * @param string $model * @return void */ public function __construct(HasherContract $hasher, $model) { $this->model = $model; // the model instance passed from `boot` method. $this->hasher = $hasher; // hasher of course. } ///rest of the code....

Hope this will solve your issue.

Usman

Hi @usm4n

I've followed too your guidance and i don't understand my problem's, can you help me

You have the details of my problem in my gists, i resume :

In my CustomUserProvider.php i get my Fake user after attempt, but i loose the user after redirection in Authenticate.php i think a don't understand or i forget a step...

Do you have Idea ?

Thanks

Thanks Usman! with your help I figured out what the problems were. In addition to what you pointed out, it kept erroring because I had the following inside AppServiceProvider.php, which was getting called before the CustomAuthProvider.php:

public function boot()
{
    view()->composer('layouts.default', function($view){
        $view->with('currentUser', $this->app['auth']->user());
    });
}

Once I moved the CustomAuthProvider to be loaded BEFORE I tried to send the ->user() message, it worked just fine!

Thanks alot for the walkthrough. One thing i'm not sure on is how to extend (or overwrite) the Guard class. For instance if I wanted to extend the user() function to return a different model depending on the type of user or return a Guest model when using Auth::user() rather than null. How would I go about that?

Worked great for me on Laravel 5.1, thanks for sharing.

Sweeeeeet. And I thought I was gonna have to write a migration just to make my DB work with Laravel. :)

Thanks for sharing the solution.

@usm4n

I did everything. It seems works, no any error from Laravel 5. But I can not login. it gives me an error message: Login or password is wrong.

So, should I write sql query by myself? If yes, how?

@usm4n

thanks for the tutorial. Just one thing I had to change to make it work (maybe specific to Laravel 5.2 ?) : in my AuthServiceProvider I had to call

$this->app['auth']->provider(...

instead of $this->app['auth']->extend(...

Same here, I also had to call provider instead of extend in Laravel 5.2. Huge help when I could never find this noted anyplace else.

hi guys thanks for this discussion I had a same problem and this helped but now I try to log in but laravel still references the laravel attributes instead of my built in ones on the user model how can I solve that I am using the example provided here just changed the attributes to meet mine and also working in laravel 5.2 the error

ErrorException in CustomUserProvider.php line 96:
Undefined index: Username
in CustomUserProvider.php line 96
at HandleExceptions->handleError('8', 'Undefined index: Username', 'CustomUserProvider.php', '96', array('credentials' => array('email' => 'email', 'password' => 'pass'))) in CustomUserProvider.php line 96
at CustomUserProvider->retrieveByCredentials(array('email' => 'email', 'password' => 'pass')) in SessionGuard.php line 353
at SessionGuard->attempt(array('email' => 'email', 'password' => 'pass'), false) in AuthenticatesUsers.php line 74
at AuthController->login(object(Request))
at call_user_func_array(array(object(AuthController), 'login'), array(object(Request))) in Controller.php line 80
at Controller->callAction('login', array(object(Request))) in ControllerDispatcher.php line 146
at ControllerDispatcher->call(object(AuthController), object(Route), 'login') in ControllerDispatcher.php line 94