Use multiple Guards for Laravel Authentication with Backpack for Laravel

1.7k Views Asked by At

I have my Laravel auth.php setup with multiple providers and multiple guards.

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


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

Within config/backpack/base.php it has an option where you can set 'guard' => null. I'd like to configure this so that it looks at both the account and the web guard and not just the default web guard. I understand I can change this, but I want to allow users with either a web or a account guard to access the backpack admin.

1

There are 1 best solutions below

1
On

WARNING

I've tested the below up to the point of logging in (with a "user" and an "account" login and everything worked as expected. I've not tested the other auth functionality, ie registration, forgotten password emails, password resets. I expect they will work as is given the below changes but you might need to tweak them a bit if you run into issues, Also, if you allow users with the same credentials in both the users and accounts tables, that's probably going to create unexpected results so you'll likely want to prevent that.

Assuming you are using all the default Backpack controllers, or at least havent modified them much...

One way accomplish this would be to do the following:

  1. run composer require funkjedi/composer-include-files see here, this will allow you to load your own helper file before Backpack tries to load its helper functions.

  2. create a custom helper file at app/Helpers/Backpack.php with this content:

    <?php
     if (! function_exists('backpack_guard_name')) {
         /*
          * Returns the name of the guard defined
          * by the application config
          */
         function backpack_guard_name()
         {
             $guards = array_keys(config('auth.guards'));
             return implode(',', $guards);
         }
     }
    
     if (! function_exists('backpack_auth')) {
         /*
          * Returns the user instance if it exists
          * of the currently authenticated admin
          * based off the defined guard.
          */
         function backpack_auth()
         {
             return \Auth::guard(find_current_guard());
         }
     }
    
     if (! function_exists('find_current_guard')) {
         /*
          * Returns the guard name being used by the
          * currently authenticated user, or the default
          */
         function find_current_guard()
         {
             // set to the default to start with
             $guard = config('backpack.base.guard');
             // get all possible guard names
             $guards = array_keys(config('auth.guards'));
             foreach ($guards as $currentGuard) {
                 if (\Auth::guard($currentGuard)->check()) {
                     $guard = $currentGuard;
                     break;
                 }
             }
             return $guard;
         }
     }
    
  3. Update your composer.json file like so:

    "extra": {
         "laravel": {
             "dont-discover": []
         },
         "include_files": [
             "app/Helpers/Backpack.php"
         ]
     },
    
  4. create a custom login controller at app/Http/Controllers/Admin/Auth/LoginController.php with this content (or wherever you want, just adjust the later steps if you put it elsewhere)

     namespace App\Http\Controllers\Admin\Auth;
    
     use Illuminate\Http\Request;
    
     class LoginController extends \Backpack\CRUD\app\Http\Controllers\Auth\LoginController
     {
    
         /**
          * Attempt to log the user into the application.
          *
          * @param  \Illuminate\Http\Request  $request
          * @return bool
          */
         protected function attemptLogin(Request $request)
         {
             $loggedIn = false;
             // get all possible guard names
             $guards = array_keys(config('auth.guards'));
             foreach ($guards as $currentGuard) {
                 $loggedIn = \Auth::guard($currentGuard)->attempt(
                     $this->credentials($request), $request->filled('remember')
                 );
                 if ($loggedIn) {
                     break;
                 }
             }
    
             return $loggedIn;
         }
    
     }
    
  5. inside routes/backpack/custom.php (create if it doesnt exist) add this code, notice that here we are including all the default Backpack routes but then we comment out the Login route and at the bottom, we add our own login route pointing to the controller we created above:

     use Illuminate\Support\Facades\Route;
     // This file is here so the backpack package will see that,
     // and load this file, instead of the one in the package
    
    
    
     /*
     |--------------------------------------------------------------------------
     | Backpack\Base Routes
     |--------------------------------------------------------------------------
     |
     | This file is where you may define all of the routes that are
     | handled by the Backpack\Base package.
     |
     */
    
     Route::group([
         'namespace'  => 'Backpack\CRUD\app\Http\Controllers',
         'middleware' => config('backpack.base.web_middleware', 'web'),
         'prefix'     => config('backpack.base.route_prefix'),
     ], function () {
         // if not otherwise configured, setup the auth routes
         if (config('backpack.base.setup_auth_routes')) {
             // Authentication Routes...
             Route::get('login', 'Auth\LoginController@showLoginForm')->name('backpack.auth.login');
            // Route::post('login', 'Auth\LoginController@login');  // COMMENT OUT THIS LINE HERE
             Route::get('logout', 'Auth\LoginController@logout')->name('backpack.auth.logout');
             Route::post('logout', 'Auth\LoginController@logout');
    
             // Registration Routes...
             Route::get('register', 'Auth\RegisterController@showRegistrationForm')->name('backpack.auth.register');
             Route::post('register', 'Auth\RegisterController@register');
    
             // Password Reset Routes...
             Route::get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('backpack.auth.password.reset');
             Route::post('password/reset', 'Auth\ResetPasswordController@reset');
             Route::get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('backpack.auth.password.reset.token');
             Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('backpack.auth.password.email');
         }
    
         // if not otherwise configured, setup the dashboard routes
         if (config('backpack.base.setup_dashboard_routes')) {
             Route::get('dashboard', 'AdminController@dashboard')->name('backpack.dashboard');
             Route::get('/', 'AdminController@redirect')->name('backpack');
         }
    
         // if not otherwise configured, setup the "my account" routes
         if (config('backpack.base.setup_my_account_routes')) {
             Route::get('edit-account-info', 'MyAccountController@getAccountInfoForm')->name('backpack.account.info');
             Route::post('edit-account-info', 'MyAccountController@postAccountInfoForm')->name('backpack.account.info.store');
             Route::post('change-password', 'MyAccountController@postChangePasswordForm')->name('backpack.account.password');
         }
     });
    
     // Load our custom login route
     Route::group([
         'prefix'     => config('backpack.base.route_prefix', 'admin'),
         'middleware' => config('backpack.base.web_middleware', 'web'),
         'namespace'  => 'App\Http\Controllers\Admin',
     ], static function () {
         // Authentication Routes...
         Route::post('login', 'Auth\LoginController@login');
     });