7

I am getting error while making custom authentication for my laravel 5.2 however this code works fine on my laravel 5.1 My config/auth.php file

'providers' => [
    'users' => [
        'driver' => 'custom',
        'model' => App\User::class,
    ],

    // 'users' => [
    //     'driver' => 'database',
    //     'table' => 'users',
    // ],
],

My CustomUserProvider.php (Auth/CustomUserProvider) file

    <?php namespace App\Auth;

use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;

class CustomUserProvider implements UserProvider {

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

    }

}

My CustomAuthProvider.php file

    <?php namespace App\Providers;

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

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

}

Now this works fine in laravel 5.1 in 5.2 i am getting error like

InvalidArgumentException in CreatesUserProviders.php line 40:
Authentication user provider [custom] is not defined.
ujwal dhakal
  • 2,289
  • 2
  • 30
  • 50
  • I think in boot method you have to use App::provider to register your custom user provider with the application. The way you have used is it alternate way of doing the same thing? – Alankar More Feb 17 '16 at 10:25
  • Have look in documentation for more details. https://laravel.com/docs/5.2/authentication#adding-custom-user-providers – Alankar More Feb 17 '16 at 10:26
  • @AlankarMore i have registered my service provider and autoloded the files – ujwal dhakal Feb 17 '16 at 10:58
  • Try by changing `'driver' => 'custom',` to `'driver' => 'customUser'`, and `$this->app['auth']->extend('custom',function()` to `$this->app['auth']->extend('customUser',function()` – Alankar More Feb 17 '16 at 11:00
  • InvalidArgumentException in CreatesUserProviders.php line 40: Authentication user provider [customUser] is not defined. – ujwal dhakal Feb 17 '16 at 11:02

4 Answers4

6

The only point is to use

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

instead of

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

The last one is used in 5.1, the first one should be used in 5.2.

shukshin.ivan
  • 11,075
  • 4
  • 53
  • 69
2

app/Models/User.php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable {
protected $connection='conn';
protected $table='users-custom';

/**
 * The attributes that are mass assignable.
 *
 * @var array
 */
protected $fillable = [
    'login', 'passwd'
];

/**
 * The attributes excluded from the model's JSON form.
 *
 * @var array
 */
protected $hidden = [
    'passwd',
];

public function getAuthPassword(){
    //your passwor field name
    return $this->passwd;
}

public $timestamps = false;

}

create app/Auth/CustomUserProvider.php

 namespace App\Auth;

use Illuminate\Support\Str;

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

/**
 * Description of 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 class name of model
 * @return void
 */
public function __construct($model) {
    $this->model = $model;        
}

/**
 * Retrieve a user by their unique identifier.
 *
 * @param  mixed  $identifier
 * @return \Illuminate\Contracts\Auth\Authenticatable|null
 */
public function retrieveById($identifier) {
    return $this->createModel()->newQuery()->find($identifier);
}

/**
 * Retrieve a user by their unique identifier and "remember me" token.
 *
 * @param  mixed  $identifier
 * @param  string  $token
 * @return \Illuminate\Contracts\Auth\Authenticatable|null
 */
public function retrieveByToken($identifier, $token) {
    $model = $this->createModel();

    return $model->newQuery()
                    ->where($model->getAuthIdentifierName(), $identifier)
                    ->where($model->getRememberTokenName(), $token)
                    ->first();
}

/**
 * Update the "remember me" token for the given user in storage.
 *
 * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
 * @param  string  $token
 * @return void
 */
public function updateRememberToken(UserContract $user, $token) {
    $user->setRememberToken($token);

    $user->save();
}

/**
 * Retrieve a user by the given credentials.
 *
 * @param  array  $credentials
 * @return \Illuminate\Contracts\Auth\Authenticatable|null
 */
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();
}

/**
 * Validate a user against the given credentials.
 *
 * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
 * @param  array  $credentials
 * @return bool
     */
    public function validateCredentials(UserContract $user, array $credentials) {
//your method auth
        $plain = $credentials['password'];
        return  md5($plain)==md5($user->getAuthPassword());
    }

/**
 * Create a new instance of the model.
 *
 * @return \Illuminate\Database\Eloquent\Model
 */
public function createModel() {
    $class = '\\' . ltrim($this->model, '\\');
    return new $class;
}

/**
 * Gets the hasher implementation.
 *
 * @return \Illuminate\Contracts\Hashing\Hasher
 */
public function getHasher() {
    return $this->hasher;
}

/**
 * Sets the hasher implementation.
 *
 * @param  \Illuminate\Contracts\Hashing\Hasher  $hasher
 * @return $this
 */
public function setHasher(HasherContract $hasher) {
    $this->hasher = $hasher;

    return $this;
}

/**
 * Gets the name of the Eloquent user model.
 *
 * @return string
 */
public function getModel() {
    return $this->model;
}

/**
 * Sets the name of the Eloquent user model.
 *
 * @param  string  $model
 * @return $this
 */
public function setModel($model) {
    $this->model = $model;

    return $this;
}

}

in config/auth.php

'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users_office',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
    ],


'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],


'users_office' => [
        'driver' => 'customUser',
        'model' => App\Models\User::class,
    ],
// 'users' => [
//     'driver' => 'database',
//     'table' => 'users',
// ],
],

in \vendor\laravel\framework\src\Illuminate\AuthCreatesUserProviders.php

 public function createUserProvider($provider)
{
    $config = $this->app['config']['auth.providers.'.$provider];    


    if (isset($this->customProviderCreators[$config['driver']])) {
        return call_user_func(
            $this->customProviderCreators[$config['driver']], $this->app, $config
        );
    }

    switch ($config['driver']) {
        case 'database':
            return $this->createDatabaseProvider($config);
        case 'eloquent':
            return $this->createEloquentProvider($config);
        case 'customUser':
            return $this->createCustomUserProvider($config);
        default:
            throw new InvalidArgumentException("Authentication user provider [{$config['driver']}] is not defined.");
    }
}


protected function createCustomUserProvider($config){        
        return new \App\Auth\CustomUserProvider($config['model']);
    }

add App\Providers\CustomUserAuthProvider.php

    namespace App\Providers;

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

/**
 * Description of CustomAuthProvider
 *
 */

class CustomUserAuthProvider extends ServiceProvider {

/**
 * Bootstrap the application services.
 *
 * @return void
 */
public function boot()
{        
     Auth::extend('customUser', function($app) {
        // Return an instance of Illuminate\Contracts\Auth\UserProvider...
        return new CustomUserProvider(new User);
    });
}

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

}
  • 1
    This is a solution but it's too dirty. I viable solution shouldn't include changes in framework itself, especially the vendor folder, or the framework is broken. In 4.2 it was achievable in a clean fashion and I believe there has to be a way to register custom creators into `$customProviderCreators` property of `CreatesUserProviders`. – Tala Nov 05 '16 at 12:02
1

Try by replacing the boot function as below:

public function boot()
{
    Auth::provider('custom', function($app, array $config) {
        // Return an instance of Illuminate\Contracts\Auth\UserProvider...
        return new CustomUserProvider($app['custom.connection']);
    });
}
Alankar More
  • 1,107
  • 2
  • 8
  • 26
  • Wew i been trying the same thing like $this->app['auth'] and not working btw what does custom.connection stands for i mean in php about . ? – ujwal dhakal Feb 17 '16 at 14:41
  • I think it may return the connection of your custom user provider. So whatever model you have used with your custom user provider driver that model instance will be return by this custom.connection. I am not sure need to dig in Laravel API docs. Is your UserContract Model extends to User Model? – Alankar More Feb 18 '16 at 06:42
1

Replace the boot function as below:

public function boot()
    {
        Auth::provider('customUser', function($app, array $config) {
            return new CustomUserProvider($config['model']);
        });
    }