phplaravellaravel-5.4

How to add a custom User Provider in Laravel 5.4


I have a Laravel 5.4 app, in which I have to authenticate my admin users from an external API, which when successfully logged in it returns a JSON with user information.

I am creating a custom guard to make this:

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

        'custom' => [
            'driver' => 'session',
            'provider' => 'customusers'
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
    ],

and this is my custom provider:

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

    'customusers' => [
        'driver' => 'jsonresponse',
        'model' => App\Admin::class,
    ]
],

After that, I am not sure how to continue. I've read some tutorials like the one from George Buckingham, and I have created a custom User provider (Right now I just need it to extend from EloquentUserProvider, eventually I will override some functions to connect to the API)

<?php

namespace App\Providers;

use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Support\Str;

class CustomUserProvider extends EloquentUserProvider { 

}

then registered it both in App\Providers\AuthServiceProvider

public function boot()
{
    $this->registerPolicies();

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

and in config/app.php

'providers' => [

    // Lots of other providers

    // Own providers
    App\Providers\CustomUserProvider::class,
],

But after that, I get the following error:

Argument 1 passed to Illuminate\Auth\EloquentUserProvider::__construct() must be an instance of Illuminate\Contracts\Hashing\Hasher, instance of Illuminate\Foundation\Application given, called in /var/www/public/iberorides/vendor/laravel/framework/src/Illuminate/Foundation/Application.php on line 612 and defined

If I override the constructor of my CustomUserProvider and change the params in the closure in AuthServiceProvider, I get the following error:

Argument 1 passed to Illuminate\Foundation\Application::bootProvider() must be an instance of Illuminate\Support\ServiceProvider, instance of App\Providers\IberoUserProvider given, called in /var/www/public/iberorides/vendor/laravel/framework/src/Illuminate/Foundation/Application.php on line 771 and defined

This makes me think I am not doing things the right way.

Could someone put me in the right direction?

Thank you so much.


Solution

  • The solution was simple.

    First, despite what other tutorials said, you do not have to register the CustomUserProvider in your config providers (Laravel 5.4 here). This was the cause of the errors I was getting.

    I only had to override two methods from EloquentUserProvider, retrieveByCredentials(array $credentials) where you return a model based on the credentials provided, and validateCredentials(UserContract $user, array $credentials) where you return a boolean depending on whether credentials are correct.

    You can use this same custom provider class with many providers, not just one, e.g.

    'providers' => [
        'customusers' => [
            'driver' => 'jsonresponse',
            'model' => App\User::class,
        ],
    
        'customadmins' => [
            'driver' => 'jsonresponse',
            'model' => App\Admin::class,
        ],
    ],
    

    After that, when you need to check auth with any provider, you need to provide the provider as guard e.g. Auth::guard('customusers').