Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5 : Restrict access to controllers by User group

I've started learning Laravel 5.1 and so far I'm liking it! But there is one thing I don't get yet..
In my previous project I had 2 specific controllers (eg: "normal", "extended") which , after a successfull login, were called based on the Users user_group from the database.

If "Foo.Bar" enters his valid credentials and has the group normal he is redirected to NormalControler. Since I wasn't using any framework I restricted access to the other group by setting a $_SESSION with the group and checking it. So if another group tried to access that controller he got redirected.

How would this be achievable in Laravel 5? So far I have a controller which is callable without an Authentication and one restricted by this code in routes.php :

// All routes in the group are protected, only authed user are allowed to access them
Route::group(array('before' => 'auth'), function() {

    // TO-DO : Seperate Controller access
});

And the login looks like this :

public function performLogin()
    {   

        $logindata = array(
            'username' => Input::get('user_name'),
            'password' => Input::get('user_pass')
        );

        if( Auth::attempt( $logindata ) ){
            // return \Redirect::to( check group and access this controller based on it);
        }
        else {
           // TO-DO : Redirect back and show error message
           dd('Login failed!');
        }
    }

----- EDIT -----

I've run the artisan command and made this middleware as you suggested :

namespace App\Http\Middleware;

use Closure;
use Request;

class GroupPermissions
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next, $group)
    {
        // Check User Group Permissions
        if( $request->user()->group === $group ){
            // Continue the request
            return $next($request);
        }

        // Redirect
        return redirect('restricted');
    }
}

and edited this line into Kernel.php into $routeMiddleware :

'group.perm' => \App\Http\Middleware\GroupPermissions::class

I think this is done right so far, correct me if I'm wrong! Could I then do something like this to restrict the controllers?

Route::group(array('before' => 'auth'), function() {

    Route::group( ['middleware' => 'group.perm', 'group' => 'normal'], function(){
        Route::get('/normal/index', 'DummyNormalController@index');
    });

    Route::group( ['middleware' => 'group.perm', 'group' => 'extended'], function(){
        Route::get('/extended/index', 'DummyExtendedController@index');
    });

});
like image 979
Krenor Avatar asked Jul 16 '15 06:07

Krenor


2 Answers

Ok, here is what you might do. Once user is logged in, you would check his credentials, get his user_group and decide what controller he should be redirected to.

if( Auth::attempt( $logindata ) ){
    $user = Auth::user();

    if ($user->inGroup('normal')) {
         return redirect()->route('normal_controllers_named_route');
    }
    return redirect()->route('extended_controllers_named_route');
}

return redirect()->back()->withFlashMessage('don\'t get me wrong');

This will handle right routing after logging in.

The next portion where you need to protect you routes from unwanted user groups may be achieved with middlewares.

  1. do an artisan command php artisan make:middleware ShouldBeInGroup
  2. go to app/http/Kernel.php and add your new middleware to the routeMiddleware array. Key of the item might be anything you like. Let's call in inGroup. So: 'inGroup' => 'App\Http\Middleware\ShouldBeInGroup'
  3. Now, in your controller, in constructor, you are able to call this middleware

$this->middleware('inGroup:extended'); //we also passing the name of the group

  1. at lastly, work on the our middleware. Open newly created ShouldBeInGroup class and edit the handle method.

    public function handle($request, Closure $next, $groupName)
    {
        if (Auth::check() && Auth::user()->inGroup($groupName)) {
             return $next($request);
        }
    
        return redirect('/');
    }
    
  2. And finally you should work on inGroup method, that should return true of false. I assume that you have user_group field your users table. Then in your User eloquent model add the method

    public function inGroup($groupName) {
        return $this->user_group == $groupName;
    }
    

Edit

if you want to use this middleware in your routes, you can do the following

Route::group(array('before' => 'auth'), function() {
    Route::get('/normal/index', ['middleware' => 'group.perm:normal', 'uses' =>'DummyNormalController@index']);
}

But generally it's better to put all your middlewares into your Controller's constructor

public function __construct(){
    $this->middleware('group.perm:normal'); // you can also pass in second argument to limit the methods this middleware is applied to : ['only' => ['store', 'update']];
}

And also on this note, Laravel provides built in auth middleware that you can use

public function __construct(){
    $this->middleware('auth');
    $this->middleware('group.perm:normal');
}

so then your routes would become much cleaner, just:

Route::get('normal/index', 'DummyNormalController@index');
like image 105
Almazik G Avatar answered Oct 30 '22 20:10

Almazik G


I think the best way to do that is using middlewares. See the doc here

You can easily create a middleware using the following artisan command:

php artisan make:middleware ExtendedMiddleware

If you can't or don't want to use artisan, you need to create a class in The App/Http/Middleware folder.

In this class you'll need the following method to handle the request. In the method you can check for the user group.

public function handle($request, Closure $next)
{
    // check user group
    if( user_group_ok )
        return $next($request); // Continue the request

    return redirect('restricted'); // Redidrect 
}

You can then use this middleware in your route.php file:

Route::group(['middleware' => 'auth'], function()
{

    // Logged-in user with the extended group
    Route::group(['middleware' => 'extended'], function()
    {
        // Restricted routes here
    });

    // Normal routes here

});
like image 37
Needpoule Avatar answered Oct 30 '22 20:10

Needpoule