Back

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


adaojunior posted 3 years ago

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

pzotov replied 3 years ago

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

adaojunior replied 3 years ago

@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 replied 3 years ago 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!

usm4n replied 3 years ago

@pzotov Thanks for sharing my article!

adaojunior replied 3 years ago

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

adaojunior replied 3 years ago

@usm4n works fine, thank you.

usm4n replied 3 years ago

No problem :)!

jedwards1211 replied 2 years ago

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

randolfarevalo replied 2 years ago

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

josh7weaver replied 2 years ago

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).

https://gist.github.com/josh7weaver/9de6162b442bdc3803b0

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

usm4n replied 2 years ago

@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

jcodt replied 2 years ago

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

https://gist.github.com/jcodt/f9ee49051b75df4d00bd

josh7weaver replied 2 years ago

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!

freezedriedpop replied 2 years ago

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?

larryweya replied 2 years ago

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

IngwiePhoenix replied 2 years ago

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.

Rashad replied 2 years ago

@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?

maxime replied 2 years ago

@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(...

ChioriGreene replied 1 year ago

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.

Tim3011 replied 1 year ago

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
gandra404 replied 11 months ago

After sacfolding auth with: php artisan make:auth

Than I am getting followinf error:

ErrorException in AuthManager.php line 294: Call to undefined method App\Extensions\CustomUserProvider::check() (View: ...my-api-project\resources\views\welcome.blade.php)

So, is it possible to use custom Auth with scafolded views?

After adding

public static function check()
{
    return true;
}

to CustomUserProvider I am getting follwoing error:

FatalThrowableError in AuthManager.php line 294: Call to undefined method App\Extensions\CustomUserProvider::authenticate()

Here is my CustomUserProvider:

<?php

namespace App\Extensions;

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

class CustomUserProvider implements UserProviderInterface
{
    public function retrieveById($identifier)
    {
        // TODO: Implement retrieveById() method.
    }

    public function retrieveByToken($identifier, $token)
    {
        // TODO: Implement retrieveByToken() method.
    }

    public function updateRememberToken(Authenticatable $user, $token)
    {
        // TODO: Implement updateRememberToken() method.
    }

    public function retrieveByCredentials(array $credentials)
    {
        // TODO: Implement retrieveByCredentials() method.
    }

    public function validateCredentials(Authenticatable $user, array $credentials)
    {
        // TODO: Implement validateCredentials() method.
    }

    public static function check()
    {
        return true;
    }

}

and here CustomAuthProvider:

<?php

namespace App\Extensions;

use App\User;
use App\Extensions\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()
    {
        //
    }


}
gaalgergely replied 10 months ago

I changed my AUTH_DRIVER=custom. I wrote the custom files like CustomUserProvider and CustomAuthProvider.

MY problem is that the user is not logged in after a true returns from the validateCredentials method.

WHY?

engine987 replied 8 months ago

gaalgergely said:

I changed my AUTH_DRIVER=custom. I wrote the custom files like CustomUserProvider and CustomAuthProvider.

MY problem is that the user is not logged in after a true returns from the validateCredentials method.

WHY?

Did you find a solution to your problem ? I am having the exact same issue.

mbrunogregorio replied 7 months ago

gandra404 said:

After sacfolding auth with: php artisan make:auth

Than I am getting followinf error:

ErrorException in AuthManager.php line 294: Call to undefined method App\Extensions\CustomUserProvider::check() (View: ...my-api-project\resources\views\welcome.blade.php)

So, is it possible to use custom Auth with scafolded views?

After adding

public static function check() { return true; }

to CustomUserProvider I am getting follwoing error:

FatalThrowableError in AuthManager.php line 294: Call to undefined method App\Extensions\CustomUserProvider::authenticate()

Here is my CustomUserProvider:

<?php

namespace App\Extensions;

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

class CustomUserProvider implements UserProviderInterface
{
   public function retrieveById($identifier)
   {
       // TODO: Implement retrieveById() method.
   }

   public function retrieveByToken($identifier, $token)
   {
       // TODO: Implement retrieveByToken() method.
   }

   public function updateRememberToken(Authenticatable $user, $token)
   {
       // TODO: Implement updateRememberToken() method.
   }

   public function retrieveByCredentials(array $credentials)
   {
       // TODO: Implement retrieveByCredentials() method.
   }

   public function validateCredentials(Authenticatable $user, array $credentials)
   {
       // TODO: Implement validateCredentials() method.
   }

   public static function check()
   {
       return true;
   }

}

and here CustomAuthProvider:

<?php

namespace App\Extensions;

use App\User;
use App\Extensions\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()
   {
       //
   }


}

Hey man, did you found the solution? I got the same trouble and can't fix it. Help me pls

Jessica Barnes replied 2 months ago

It is necessary to use Laravel authentication controller when we use custom authentication driver...About the solution, already @usm4n gave a great solution for the custom authentication. For any query regarding Laravel development, just visit; hirelaraveldeveloperindia.com

sman replied 3 days ago

In my case, the key was to understand retrieveById() and retrieveByCredentials. I believe it is mandatory that they return the proper info for this to work. I figured it out by doing var_dump(Auth::user()) on a default install and comparing it to what my custom auth provider install was doing. Also found a brief comment in Laravel docs that I had missed before.

https://laravel.com/docs/5.5/authentication#adding-custom-user-providers

The retrieveById function typically receives a key representing the user, such as an auto-incrementing ID from a MySQL database. The Authenticatable implementation matching the ID should be retrieved and returned by the method.

So retrieveById and retreiveByCredentials should both return the same object. The same as the default auth scaffold returns from User Model. I am pretty sure this is mandatory for Auth to work. Only in this case it will return your Custom Model such as Admin.php or whatever.

I don't think any other Methods in CustomUserProvider need to return anything except ValidateCredentials() which can just be set to return true; for testing


Sign in to participate in this thread!



We'd like to thank these amazing companies for supporting us