How to implement multiple authentication drivers

0

I am building a system where two types of authentication are required, the first one for ordinary users, who will go to the front of the store, and the second for administrators, who will access the admin environment.

The problem: by default Laravel 5 has only one authentication driver, which allows ordinary users logged in to the store to access the administration environment, and vice versa.

Identifying what is user and what is administrator is even easy with a system of levels (roles), but is not as effective as the division of these sessions.

How can I implement a second authentication session for administrators only? such as Auth::admin()

    
asked by anonymous 05.05.2015 / 12:05

1 answer

1

You can "emulate" a new Auth Class.

The Laravel Auth component is basically the Illuminate \ Auth \ Guard class, and this class has some dependencies.

So basically you have to create a new Guard class ...

class CilentGuard extends AuthGuard {

public function getName()
{
    return 'login_' . md5('ClientAuth');
}

public function getRecallerName()
{
    return 'remember_' . md5('ClientAuth');
    }
}

And a ServiceProvider to initialize the class, passing the dependencies.

<?php 

use Illuminate\Support\ServiceProvider;
use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Hashing\BcryptHasher;
use Illuminate\Auth\Reminders\PasswordBroker;
use Illuminate\Auth\Reminders\DatabaseReminderRepository;
use ClientGuard;
use ClientAuth;

class ClientServiceProvider extends ServiceProvider 
{

    public function register()
    {
        $this->registerAuth();
        $this->registerReminders();
    }

    protected function registerAuth()
    {
        $this->registerClientCrypt();
        $this->registerClientProvider();
        $this->registerClientGuard();
    }

    protected function registerClientCrypt()
    {
        $this->app['client.auth.crypt'] = $this->app->share(function($app)
        {
            return new BcryptHasher;
        });
    }

    protected function registerClientProvider()
    {
        $this->app['client.auth.provider'] = $this->app->share(function($app)
        {
            return new EloquentUserProvider(
                $app['client.auth.crypt'], 
                'Client'
            );
        });
    }

    protected function registerClientGuard()
    {
        $this->app['client.auth'] = $this->app->share(function($app)
        {
            $guard = new Guard(
                $app['client.auth.provider'], 
                $app['session.store']
            );

            $guard->setCookieJar($app['cookie']);
            return $guard;
        });
    }

    protected function registerReminders()
    {
        # DatabaseReminderRepository
        $this->registerReminderDatabaseRepository();

        # PasswordBroker
        $this->app['client.reminder'] = $this->app->share(function($app)
        {
            return new PasswordBroker(
                $app['client.reminder.repository'], 
                $app['client.auth.provider'], 
                $app['redirect'], 
                $app['mailer'], 
                'emails.client.reminder' // email template for the reminder
            );
        });
    }

    protected function registerReminderDatabaseRepository()
    {
        $this->app['client.reminder.repository'] = $this->app->share(function($app)
        {
            $connection   = $app['db']->connection();
            $table        = 'client_reminders';
            $key          = $app['config']['app.key'];

            return new DatabaseReminderRepository($connection, $table, $key);
        });
    }

    public function provides()
    {
        return array(
            'client.auth', 
            'client.auth.provider', 
            'client.auth.crypt', 
            'client.reminder.repository', 
            'client.reminder', 
        );
    }
}

In this Service Provider, I've put some examples of how to create a 'new' component to remember the password. Now you need to create two new facades, one for authentication and one for remembering the password.

<?php 
use Illuminate\Support\Facades\Facade;

class ClientAuth extends Facade
{

    protected static function getFacadeAccessor() 
    {
        return 'client.auth';
    }
}

E

<?php 
use Illuminate\Support\Facades\Facade;

class ClientPassword extends Facade
{

    protected static function getFacadeAccessor() 
    {
        return 'client.reminder';
    }
}

Of course, to remember the password, you need to create the table in the database in order to work. In this example, the table name must be client_reminders, as you can see in the registerReminderDatabaseRepository method in the Service Provider. The table structure is the same as the original table. After that, you can use your ClientAuth in the same way you use the Auth class. And the same thing for ClientPassword with the Password Class.

ClientAuth::gust();
ClientAuth::attempt(array('email' => $email, 'password' => $password));

ClientPassword::remind($credentials);

Do not forget to add your service provider to the service providers list in the app/config/app.php file.

    
06.05.2015 / 13:36