Support the ongoing development of Laravel.io →
Authentication
Last updated 1 year ago.
0

@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;
});
Last updated 1 year ago.
0
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!

Last updated 1 year ago.
0

@pzotov Thanks for sharing my article!

Last updated 1 year ago.
0

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

Last updated 1 year ago.
0

@usm4n works fine, thank you.

Last updated 1 year ago.
0

No problem :)!

Last updated 1 year ago.
0

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

0

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

0

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!

Last updated 9 years ago.
0

@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

Last updated 9 years ago.
0

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

0

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!

Last updated 8 years ago.
0

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?

0

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

0

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.

0

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

0

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

Last updated 8 years ago.
0

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.

0

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
Last updated 7 years ago.
0

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()
    {
        //
    }


}
Last updated 7 years ago.
0

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?

0

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.

0

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

0

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

0

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

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

Last updated 6 years ago.
0

Since Laravel 5.5 is out now, I will explain the process for this version. To add custom authentication in Laravel 5.5, you have to add auth to your main controller file.

<?php
namespaceAppHttpControllers;
useRedirect;
useAuth;
useInput;
useIlluminateSupportFacadesValidator;
useIlluminateFoundationBusDispatchesJobs;
useIlluminateRoutingController as BaseController;
useIlluminateFoundationValidationValidatesRequests;
useIlluminateFoundationAuthAccessAuthorizesRequests;
useIlluminateFoundationAuthAccessAuthorizesResources;
useIlluminateHtmlHtmlServiceProvider;
class MainController extends BaseController

{
	public

	function showLogin()
		{

		// Form View

		return view('login');
		}

	public

	function doLogout()
		{
		Auth::logout(); // logging out user
		return Redirect::to('login'); // redirection to login screen
		}

	public

	function doLogin()
		{

		// Creating Rules for Email and Password

		$rules = array(
			'email' => 'required|email', // make sure the email is an actual email
			'password' => 'required|alphaNum|min:8'

			// password has to be greater than 3 characters and can only be alphanumeric and);
			// checking all field

			$validator = Validator::make(Input::all() , $rules);

			// if the validator fails, redirect back to the form

			if ($validator->fails())
				{
				return Redirect::to('login')->withErrors($validator) // send back all errors to the login form
				->withInput(Input::except('password')); // send back the input (not the password) so that we can repopulate the form
				}
			  else
				{

				// create our user data for the authentication

				$userdata = array(
					'email' => Input::get('email') ,
					'password' => Input::get('password')
				);

				// attempt to do the login

				if (Auth::attempt($userdata))
					{

					// validation successful
					// do whatever you want on success

					}
				  else
					{

					// validation not successful, send back to form

					return Redirect::to('checklogin');
					}
				}
			}
		}

0

Sign in to participate in this thread!

Eventy

Your banner here too?

Moderators

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

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2024 Laravel.io - All rights reserved.