Protecting Routes with Role Permissions using middleware Laravel - php

I have a multilevel members website and need to protect my routes in the web.php file in Laravel 5.5.
I have a column on my users table called role_id.
In role_id is the following values
NULL (For New Users)
1 (For Owner)
2 (For Admin)
3 (For Moderators)
4 (For Banned Users)
I was trying to do it with a simple IF statement
if (Auth::user()->role_id != '2'):
return view('home');
else:
//ADMIN ROUTES
Route::get('/admin','AdminController#index')->name('admin');
endif;
if (Auth::user()->role_id != '1'):
return view('home');
else:
//OWNER ROUTES
Route::get('/admin','OwnerController#index')->name('owner');
endif;
ETC....
But get Error Trying to get property of non-object. Also probably not the best way to do that.
So I read about doing it with MIDDLEWARE like this: (Looks much better)
Route::group(['middleware' => ['auth', 'admin']], function() {
// put all your admin routes here
});
Route::group(['middleware' => ['auth', 'owner']], function() {
// put all your owner user routes here
});
But it didn't explain how to add the Middleware.
Would I have to create 5 different Middleware files for each group similar to file I found:
use Illuminate\Contracts\Auth\Guard;
class Admin
{
protected $auth;
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
public function handle($request, Closure $next)
{
if($this->auth->user()->role_id != '2') {
return redirect()->view('home');
}
return $next($request);
}
}
Could someone lend a helping hand and explain how to write the correct middleware to achieve this?

web.php
Route::group(['middleware' => ['auth', 'admin']], function() {
Route::get('/admin/dashboard', function(){
return view('admin.dashboard');
});
});
into protected $routeMiddleware of Kernel.php
'admin' => \App\Http\Middleware\AdminMiddleware::class,
AdminMiddleware.php
$user = Auth::user();
if($user->role == 'admin'){
return $next($request);
} else
// abort(403, 'Wrong Accept Header');
return new Response(view('notauthorized')->with('role', 'admin'));
}
admin, moderators, owner, banned_user will be value of user_type/role column of user table.
or you can use user_type_id or role_id instead of user_type_name or role_type
Don't forget to add
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Response;
just under the
use Closure;
of your Middleware
You can also do it with other ways like Gate, let me know if you need it. :)

Like this example:
Route::get('/cart/payment', 'CartController#getcartpayment')->middleware('checkAuth');
$user = Sentinel::findById($user_id);
$role= $user->role();

Error Trying to get property of non-object. Can be found if user not logged in yet.
Before u check
if (Auth::user()->role_id != '2'):
u should make sure that user is logged in with
Auth::check()
first...

Related

How can I restrict API info to user? Laravel 5.7

I already have authentication with api_token working correctly, but I want my consumer to make an API request and return the info respecting only to his user_id.
I know I can do this by passing info in the URL, as I have it right now in Route::get('/getOrder/{user_id}','OrderController#indexByUser'); but I'm afraid that any user could just enter another user_id and get the orders from another User.
api.php
<?php
use Illuminate\Http\Request;
Route::post('login', 'Auth\LoginController#login');
Route::post('logout', 'Auth\LoginController#logout');
Route::group(['middleware' => 'auth:api'], function() {
Route::get('/user', function (Request $request) {
return $request->user();
});
Route::get('/getOrder/{user_id}','OrderController#indexByUser');
});
Login and Logout gives/clears api_token respectively.
Thanks in advance.
You can create own midlleware, were set this logic.
public function handle($request, Closure $next, ...$guards)
{
if (Auth::user()->getId() !== $request->getPathInfo()) { // if userId contains in path
return redirect(back(413));
}
return parent::handle($request, $next, $guards);
}
(this is only example code )
Or you can use policies
https://laravel.com/docs/8.x/authorization#writing-policies

What is the execution sequence (which after which) among web.php, LoginController.php and AdminMiddleWare.php in Laravel

If I login with user type 'admin' then how does the code sequence will be executed? In which states Admin Middleware works or Login Controller or Routes. And redirectTo() function of Login Controller returns 'dashboard' or 'home' to where. Please helps me in details
web.php or route
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
Route::group(['middleware' => ['auth','admin']],function(){
Route::get('/dashboard',function(){
return view('admin.dashboard');
});
});
LoginController.php
protected function redirectTo(){
if(Auth::user()->usertype == 'admin'){
return 'dashboard';
}
else{
return 'home';
}
}
AdminMiddleware.php
public function handle($request, Closure $next)
{
if(Auth::user()->usertype == 'admin'){
return $next($request);
}
else{
return redirect('/home');
}
}
After user login: (in case of usertype == admin)
1- The function of redirectTo() in LoginController.php will be executed.
2- The logged in user will be checked by the AdminMiddleware.
3- The user will reach the route admin.dashboard function, according to the result of the AdminMiddleware.
After user login: (in case of usertype != admin)
1- The function of redirectTo() in LoginController.php will be executed.
2- The user will reach the route home function, according to the result of the LoginController.php.

Laravel 6 - Auth::guard('user')->user return null

I create a multiple Authentication in Laravel. When I login with user, on debug in post login method, after Auth::guard('user')->attempLogin..... I see a user but after redirect to HomeController this return null.
How to resolve? I'm beginner in Laravel.
Thank's!!!
/routes/auth/user.php
Route::prefix('backoffice')->name('user.')->namespace('User')->middleware('user')->group(function () {
Auth::routes();
Route::get('home', 'HomeController#index')->name('home');
});
/routes/web.php
Route::group(['middleware' => 'web'], function() {
require 'auth/user.php';
Route::get('/', function () {
return view('welcome');
});
Route::get('/home', 'HomeController#index')->name('home');
Route::resource('cadastro', 'CadastroController');
});
/app/Controllers/User/Auth/LoginController - #post Login
public function login(Request $request) {
$credentials = [
'username' => $_POST['username'],
'password' => $_POST['password']
];
Auth::guard('user')->attempt($credentials, false);
//dd('auth', Auth::guard('user'));
return redirect()->intended('/backoffice/home');
}
/app/Controllers/User/HomeController
public function __construct()
{
$this->middleware('user');
dd('after middleware', Auth::guard('user'), Auth::guard('user')->user());
}
public function index()
{
return view('user.home');
}
By default, Laravel doesn't ship with auth guard user. Perhaps you meant to use web guard i.e Auth::guard('web'). Auth::guard()->user() should return the logged in user object if a user is logged in.
Also, the default middleware for checking logged in user is auth, not user. So, your route might look like this: Route::prefix('backoffice')->name('user.')->namespace('User')->middleware('auth')->group(function () {});, except you've defined a custom middleware in app/Http/Kernel.php $routeMiddleware array with alias user

how to limit access to go to url?

This is the code of my Middleware.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use App\Models\Role;
use App\User_roles;
use App\User;
use Route;
class OwnerMiddleware
{
public function handle($request, Closure $next)
{
$user = new User;
$current = $user->find(Auth::user()->id)->role;
$current = $current->find($current->id)->roles;
if($current->name != 'admin' && $current->name != 'oper')
{
return redirect('/');
}
return $next($request);
}
}
And this is the code of web.php
Route::group(['middleware'=>'auth'],function(){
Route::group(['middleware'=>'role'],function (){
Route::resource('users','UseCon');
});
Route::group(['middleware'=>'role:client'],function (){
});
Route::group(['middleware'=>'role:oper'],function (){
Route::get('operall', 'ApplicController#index');
Route::get('operall/drivers', 'DriversController#index')->name('driver_page');
});
});
My Question is :how can I prevent url (/ users) from going to the user whose role is:oper ?
NOTE: role (oper) should not go to those urls that roles are available
(admin)
For protecting your user routes, you can create a User middleware
php artisan make:middleware User
In App\Http\Middleware\User.php you can do something like this
public function handle($request, Closure $next)
{
// Check if user has permission to access route
if(!Auth::user()->role === 'user' ) {
return redirect()->back();
}
return $next($request);
}
Register middleware in the kernel.php
protected $routeMiddleware = [
...
'user' => \App\Http\Middleware\User::class
];
Then protect user routes with created user middleware
Route::group(['middleware'=> 'user'],function (){
Route::resource('users','UseCon');
});
Repeat same steps for 'admin' and 'oper' routes.

How to redirect according to user role using middleware?

I am doing project in laravel. I want to redirect user according to his role.
My tables are,
user table having fields (id,name,password).
role table having fields (id,role).
assigned_role table having fields (id,role_id,user_id).
I have User model as,
User.php
public function roles()
{
return $this->belongsToMany('App\Role', 'assigned_roles', 'user_id', 'role_id');
}
For that I have created one middleware named as 'RoleMiddleware'
RoleMiddleware:
public function handle($request, Closure $next)
{
$roles = $request->user()->roles;
foreach ($roles as $role) {
if($role->name != 'super-admin')
return redirect('/user');
}
return $next($request);
}
I have this middleware in kernel.php file,
Kernel.php looks like,
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'can' => \Illuminate\Foundation\Http\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'role' => \App\Http\Middleware\RoleMiddleware::class,
];
but now I don't know how to use this middleware. When I add this middleware in Route.php file as,
Route::group(['middleware' => 'web'], function () {
Route::auth();
Route::group(['middleware' => 'role'], function () {
Route::get('/home', 'HomeController#index');
Route::get('/user', 'UserController#index');
});
});
But when I did sign in process it redirects to the correct url. But now it can give access to the inside pages without checking whether user is logged in or not. Whereas when I do comment to the RoleMiddleware part it prevents to access inside pages unless and user do logging.
I don't know how to do this.
If I understood you correctly:
You want to restrict users that doesn't have the super-admin role (weither they are authenticated or not) to prevent them from accessing a certain URL.
You are also trying to redirect any authenticated users which does not have the super-admin role to the url /user.
Correct?
Here's how to do this:
In your routes.php file you need to provide routes for the super-admin user and authenticated users (without super-admin role)
Route::group(['middleware' => 'web'], function () {
Route::auth();
Route::group(['middleware' => ['auth', 'role']], function () {
// All routes you put here can only be accessible to users with super-admin role
});
Route::group(['middleware' => 'auth'], function () {
// All routes you put here can be accessible to all authenticated users
});
});
And in your role middleware you need to prevent authenticated users without the superadmin role to access the given url, in this case by simply redirecting them to another url
public function handle($request, Closure $next)
{
$roles = $request->user()->roles;
foreach ($roles as $role) {
if($role->name == 'super-admin')
// If user is super-admin, accept the request
return $next($request);
}
// If user does not have the super-admin role redirect them to another page that isn't restricted
return redirect('/user');
}

Categories