1
votes

I have two guards in laravel

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

        //Our Admin custom driver
        'web_admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
    ],

and providers

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

     //Admin user provider
      'admins' => [
          'driver' => 'eloquent',  //We are using eloquent model
          'model' => App\Admin::class,
      ],
],

The default is

'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

When i log in as admin and try to access the user profile it asks me to login as user which is normal. But what im looking for is, admin should be able to access whole site as admin login.

The reason i choose multi auth over rbac is because i have 5 types of users and each have different registration fields and login. Each user have a set of tools too.

So i want admin guard to be able to access all guards too.

Business guard to be able to access only users guard.

App/Http/Controllers/AdminAuth/LoginController

<?php

//LoginController.php

namespace App\Http\Controllers\AdminAuth;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

//Class needed for login and Logout logic
use Illuminate\Foundation\Auth\AuthenticatesUsers;

//Auth facade
use Auth;

class LoginController extends Controller
{
    //Where to redirect admin after login.
    protected $redirectTo = '/admin/home';

    //Trait
    use AuthenticatesUsers;

    //Custom guard for admin
    protected function guard()
    {
      return Auth::guard('web_admin');
    }

    //Shows admin login form
   public function showLoginForm()
   {
       return view('admin.auth.login');
   }
}

App/Http/Controllers/Auth/LoginController

<?php

namespace App\Http\Controllers\Auth;
use Socialite;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }

    /**
     * Redirect the user to the GitHub authentication page.
     *
     * @return \Illuminate\Http\Response
     */
      public function redirectToProvider($social)
      {
          return Socialite::driver($social)->redirect();
      }

      /**
       * Obtain the user information from GitHub.
       *
       * @return \Illuminate\Http\Response
       */
      public function handleProviderCallback($social)
      {
          $user = Socialite::driver($social)->user();

          // $user->token;
      }
}

Similarly i have created middleware for admin too in App/Https/Middleware/AuthenticateAdmin.php

<?php

//AuthenticateAdmin.php

namespace App\Http\Middleware;

use Closure;

//Auth Facade
use Auth;

class AuthenticateAdmin
{
   public function handle($request, Closure $next)
   {
       //If request does not comes from logged in admin
       //then he shall be redirected to admin Login page
       if (! Auth::guard('web_admin')->check()) {
           return redirect('/admin/login');
       }

       return $next($request);
   }
}

And RedirectIfAdminAuthenticated

<?php

//RedirectIfAdminAuthenticated.php

namespace App\Http\Middleware;

use Closure;

//Auth Facade
use Auth;

class RedirectIfAdminAuthenticated
{

  public function handle($request, Closure $next)
  {
      //If request comes from logged in user, he will
      //be redirect to home page.
      if (Auth::guard()->check()) {
          return redirect('/home');
      }

      //If request comes from logged in admin, he will
      //be redirected to admin's home page.
      if (Auth::guard('web_admin')->check()) {
          return redirect('/admin/home');
      }
      return $next($request);
  }
}

RedicrectIfAuthenticated

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->check()) {
            return redirect('/home');
        }

        return $next($request);
    }
}
2
You said, When i log in as admin and try to access the user profile it asks me to login as user so are you checking user profile's function to authenticate a user ? You would have written a function to check access level?Himanshu Upadhyay
You mean in controller?user6780526
If you have many types of users... so i suggest you to change your logic and make the Admin as Suer too... remove the admins and in the users add field "type" or something like that... and wotk with field to check if user is admin or have permission / access to some parts of the system... and if the user "type" is "admin" so he will have access to all parts too.shushu304
Route::group(['middleware' => 'auth'], function() { I want admin to have access to these routes too. I have created separate middle ware for admin which has its Route::group['middleware' => 'admin'] how can i make admin access auth middleware too so that the support agents can check in case if any problem arises with user accountuser6780526
@Srikanth gopi ... yes this is what i mean. I did similar thing on one of the systems that i developed, and i added one more guard so all the "logged in" routes pass in (like auth) and there i'm checking the requested rout and action and check if the user type is allow to access this action, and if not i redirected him to somewhere else (in my case to main dashboard page).shushu304

2 Answers

1
votes

Further to our correspondence

1.

If you have many types of users... so i suggest you to change your logic and make the Admin as User too... remove the admins and in the users add field "type" or something like that... and work with field to check if user is admin or have permission / access to some parts of the system... and if the user "type" is "admin" so he will have access to all parts too.

  1. so you mean remove multi auth and go for RBAC. But i have a requirement where i need to use multi auth and each guard has their own RBAC For example, admin guard roles are manager, support and so. Business guard roles are vendors, sellers and so.

  2. yes this is what i mean. I did similar thing on one of the systems that i developed, and i added one more guard so all the "logged in" routes pass in (like auth) and there i'm checking the requested rout and action and check if the user type is allow to access this action, and if not i redirected him to somewhere else (in my case to main dashboard page).

add new middleware

php artisan make:middleware Permissions

in app\Http\Kernel.php, add to protected $routeMiddleware new middleware

'permissions' => \App\Http\Middleware\Permissions::class,

in Routes web add the desire routs for logged in and add the middleware permissions ... pay attention to the as definition

Route::group(['middleware'=>['auth', 'permissions']], function() {
        // any of your routs ... for example

        Route::get('/', [
            'uses'=>"UserController@getUsers",
            'as'=>"users"
        ]);

        Route::get('/{id}', [
            'uses'=>"UserController@getUserEdit",
            'as'=>"users.edit"
        ]);
});

in the new middleware app\Http\Middleware\Permissions.php, adjust the public function handle and add there the users level logic... pay attention that for the switch case checking the as ... the same as that defined in the routs web file.

add more check as you need for the logged in user "type"... Admin, Support ... and so on as you have in the system.

public function handle($request, Closure $next, $guard = null)
{
    $user = $request->user();
    $actions = $request->route()->getAction();

    switch( $actions['as'] ) {
        case "users":
            if( ! $user->isAdmin() ) {
                //return redirect()->route("dashboard");
            }
        break;

        case "users.edit":
            if( ! $user->isAdmin() ) {

            }
        break;

        // add more cases as you need and check the user "type"

        default:

        break;
    }

    return $next($request);
}

if you have a lot of routs... so maybe it will be better to add few "little" middleware and for every route group / prefix ... check if user allow to access this prefix. for example... add SupportMiddleware / SalesMiddleware ... and in every one of them you can just check the user type and if it's fit to the current group of routes.

1
votes

Simply, seperate your guards with , (comma) then all of the listed guards can access those routes.

Example:

Route::group(['middleware'=>'auth:web,web_admin'], function() {
    //Now this routes can be accessible by both admin as well as 

});