How to add custom provider in Laravel 5.4

I have a Laravel 5.4 application where I have to authenticate admin users with an external API that returns JSON with user information on successful login.

I create my own guard to do 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'm not sure how to proceed. I read some tutorials like from George Buckingham and created my own user provider (for now I just need to extend it to 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 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 the Illuminate \ Contracts \ Hashing \ Hasher instance given by the Illuminate \ Foundation \ Application instance 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 parameters in the closure in the AuthServiceProvider, I get the following error:

Argument 1 passed to Illuminate \ Foundation \ Application :: bootProvider () must be the Illuminate \ Support \ ServiceProvider instance specified by the App \ Providers \ IberoUserProvider instance, which is invoked in / var / www / public / iberorides / vendor / laravel / framework /src/Illuminate/Foundation/Application.php on line 771 and defined

It makes me think that I am not doing things right.

Can anyone point me in the right direction?

Thank you so much.

+5


source to share


3 answers


The solution was simple.

First, despite what other tutorials have said, you don't need to register CustomUserProvider

with your config providers (Laravel 5.4 here). This was the reason for the errors I was getting.

I had to override two methods from EloquentUserProvider

, retrieveByCredentials(array $credentials)

where you return a model based on the provided credentials, and validateCredentials(UserContract $user, array $credentials)

where you return a boolean value based on the user's credentials.



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

'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 a guard, for example. Auth::guard('customusers')

...

+4


source


None of the solutions I found worked for me, so I realized that this is a very simple way. ( Laravel 5.4 )

My problem was that I had to allow users to log in with their phone number.

I am overriding EloquentUserProvider

:

class PhoneUserProvider extends EloquentUserProvider
{
    public function retrieveByCredentials(array $credentials)
    {
        if (!$credentials) {
            return null;
        }

        // Fallback to original email authorization
        if (filter_var($credentials['email'], FILTER_VALIDATE_EMAIL)) {
            return parent::retrieveByCredentials($credentials);
        }

        // Assume we are logging in with a phone number
        return UserModel::where('phone', $credentials['email'])->first();
    }
}

      



And in my upload method, AppServiceProvider

I added the following lines:

Auth::setProvider(new PhoneUserProvider(app(Hasher::class), UserModel::class));

You can even set the provider in the login controller based on some conditions, etc.

+2


source


Very small customizations to the EloquentUserProvider can be done with the following code inside the loading method of your AuthServiceProvider.

Auth::provider('eloquent', function($app, array $config)
{
  return new class($app['hash'], $config['model']) extends \Illuminate\Auth\EloquentUserProvider
  {

  };
});

      

0


source







All Articles