Monday, June 12, 2017

Laravel 5.X Authentication Custom User Providers

The custom provider let you make and bridge between your user custom authentication service and the Laravel functionality. It's easy to implement, below show full process step by step.

Stage 1: Create a User model class ->

At first you need to create a model class which will extend laravel custom model Illuminate\Foundation\Auth\User as below:

<?php
namespace App\Entity;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    /**
     * The attributes that are assignable.
     */
    protected $fillable = [
        'first_name', 'last_name'
    ];

    /**
     * The attributes excluded from the model's JSON form.
     */
    protected $hidden = [
        'password', 'remember_token'
    ];
}


Stage 2: Create a CustomValidationProvider (Data Checker) class ->


<?php
namespace App\Authentication;

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

class CustomValidationProvider implements UserProvider
{
    public function __construct($model)
    {
        $this->model = $model;
    }

    public function retrieveById($identifier)
    {
        /* Get by id */
        return $this->createModel()->newQuery()->find($identifier);
    }

    public function retrieveByToken($identifier, $token)
    {
        $model = $this->createModel();

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

    public function updateRememberToken(Authenticatable $user, $token)
    {
        $user->setRememberToken($token);
        $user->save();
    }

    public function retrieveByCredentials(array $credentials)
    {
        $query = $this->createModel()->newQuery();

        foreach ($credentials as $key => $value) {
            if (!contains($key, 'password')) {
                $query->where($key, $value);
            }
        }

        return $query->first();
    }

    public function validateCredentials(Authenticatable $user, array $credentials)
    {
        /* Match password here */
        return $user->getAuthPassword() == $credentials["password"];
    }

    public function createModel()
    {
        $class = '\\'.ltrim($this->model, '\\');
        return new $class;
    }

    static function contains($haystack, $needle)
    {
        return strpos($haystack, $needle) !== false;
    }
}

Don’t forget to register this service in your config/app.php file as below line:


'providers' => [
    App\Authentication\CustomAuthServiceProvider::class,
    ......
]

Stage 3: Register custom provider (Initialization of Provider) ->

<?php
namespace App\Authentication;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;

class CustomAuthServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Auth::provider('custom_provider', function($app, array $config) {
            return new CustomValidationProvider($config['model']);
        });
    }

    public function register()
    {

    }
}

Stage 4: Update config to use new driver ->

Open up your config/auth.php file and scroll down to the "providers" section, and simply update the driver name as shown:


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


Again, I can’t tell you how to implement these methods as it depends on how and where you’re storing your users, but as an example, you might inject an API provider via the constructor, and then make API calls to get user data, apply it to an instance of our user class, then return it.



No comments:

Post a Comment