Authorize function is not working with middleware | Laravel - laravel

I have an authorization using middleware where Function could only run when authorized
this is my middleware:
class IsAdmin
{
public function handle($request, Closure $next)
{
if (auth()->check() && auth()->user()->is_admin == 1) {
return $next($request);
}
return abort(403, 'Forbidden');
}
}
my Controller:
public function destroy(int $bookId, int $reviewId, Request $request)
{
// #TODO implement
$check_bookReview = BookReview::firstWhere('id', $reviewId)->where('book_id', $bookId);
if ($check_bookReview && isAdmin()) {
BookReview::destroy($reviewId);
return response()->noContent();
} else {
abort(404);
}
}
and my api.php as well my Kernel:
'auth.admin' => \App\Http\Middleware\IsAdmin::class
Route::group(['middleware' => ['auth.admin']], function (){
Route::post('/books', 'BooksController#store');
Route::post('/books/{id}/reviews', 'BooksReviewController#store');
Route::delete('/books/{bookId}/reviews/{reviewId}', 'BooksReviewController#destroy');
});
and i have a User db field where it contains api_token and is_admin like below:
and my Postman still return 403 forbidden while i already gave an authorization by headers:
what should i do here, to fulfill my function?

Looks like your Authenticate middleware is not working, so it likely fails on auth()->check().
Make sure to use the auth middleware from Laravel, you can also use a guard as described here:
https://laravel.com/docs/9.x/authentication#protecting-routes

Related

How to authorize before run a function in Controller| Laravel

I have an API task where I should authorize before deleting data (BookReview),
Access to this endpoint requires authentication with an API token and admin privileges.
in User table I have api_token and is_admin field:
[![User Table][1]][1]
this is my BookReviewController:
public function destroy(int $bookId, int $reviewId, Request $request)
{
// #TODO implement
$check_bookReview = BookReview::firstWhere('id', $reviewId);
if ($check_bookReview) {
BookReview::destroy($reviewId);
return response()->noContent();
} else {
abort(404);
}
}
i don't know what to add in my controller, and further more I need to authorize it from postman
[![Postman][2]][2]
the delete function works fine, but there is no authorization yet
[1]: https://i.stack.imgur.com/ywvC8.png
[2]: https://i.stack.imgur.com/fyhpG.png
If you have is_admin in your DB so you can check user is admin or not.
public function destroy(int $bookId, int $reviewId, Request $request)
{
// #TODO implement
$check_bookReview = BookReview::firstWhere('id', $reviewId);
if ($check_bookReview && auth()->user()->is_admin == 1) {
BookReview::destroy($reviewId);
return response()->noContent();
} else {
abort(404);
}
}
or in your controller:
use Auth;
if (Auth::user() && Auth::user()->is_admin == 1) {
//destroy
}
and if you want use middleware then:
in routes/web.php add:
Route::group(['middleware' => ['auth', 'admin']], function () {
Route::post('/destroy-something', 'YourController#destroy')->name('destroy.review');
});
in app/Http/Middleware create a middleware for admin.
then add it to app/Http/Kernel.php to the protected $routeMiddleware array.
You should use some middleware. The middleware is the authetication step that you are missing. In the middleware, you should make the validation like find the user by de token that he sent to you, see if he is an admin an then send the request to the controller (if he is an admin) or return an 401 status code if he is not authorized to do this.
To help you with middleware is nobody better then the documentation

How to fix this, i try to load dashboard route when the auth middleware is true

But when authentication was success, it shown error Route [/db1] not defined. I hace declared db1 route, but this route can access only if user has session. Anyone can tell me what wrong with my code?
this is my route:
Route::group(['middleware' => ['userSession']], function() { Route::get('/db1', [WasteController::class, 'db1'])->name('db1'); });
this is my kernel in middlewareGroup:
'userSession' => [ \App\Http\Middleware\CheckUserSession::class, ],
this is my middleware:
public function handle($request, Closure $next) {
if ($request->session()->get('status') != 'true') {
//status user cannot be found in session
return redirect('/');
}
return $next($request);
}
i have tried but it show error db1 route not defined
Did you try this?
public function handle($request, Closure $next) {
if ($request->session()->get('status') = 'true') {
//status user cannot be found in session
return $next($request);
}
return redirect('/');
}

Protecting Routes With Two middle-wares So that both users can access it

I am trying to protect a route using two middle-wares so that both expert and user can access the same route but as soon a user tries to access the route he is logged out.
I had created two middle-wares for expert and user and protect the route using these middle-wares.
Web.php
Route::group(['middleware' => ['expert','user']], function () {
Route::post('/showForm','UserController#showFormFilled');
});
User Middle ware
public function handle($request, Closure $next)
{
//////////////////// check if user is logged in ///////////////////
if(Auth::check())
{
////////////////// check user role id //////////////////////////
if(auth()->user()->role_id == 3)
{
return $next($request);
}
else if (auth()->user()->role_id==2)
{
return redirect('/expert');
}
}
else
{
return redirect('/login');
}
}
Expert Middle ware
public function handle($request, Closure $next)
{
if(Auth::check()){
if(auth()->user()->role_id == 2)
return $next($request);
else if (auth()->user()->role_id==3)
return redirect('/dashboard');
}
else {
return redirect('/login');
}
}
Both the users should be able to access the same route.
#hamzahummam - there is no way to achieve what you are looking for using the above separate-middlware-for-each-type method. Each middleware prematurely redirects [either to /dashboard or to /expert etc] the request without allowing it to passthrough other middleware. Best would be to use a third-party package that provides a more comprehensive and fine-grained access control [example: https://github.com/Zizaco/entrust]
If that's not an option, the best case would be to implement a single middleware and pass the role as parameter. See: Laravel Middleware Parameters
A minimal example would look like:
public function handle($request, Closure $next, $role)
{
// Assuming Auth::check() passes
$roleId = auth()->user()->role_id;
if ($roleId == 2 && strpos($role, 'expert') !== false) {
// Logged in user is `expert` and route allows `expert` access
return $next($request);
} else if ($roleId == 3 && strpos($role, 'user') !== false) {
// Logged in user is `user` and route allows `user` access
return $next($request);
} // and so on...
// Handle failures here
if ($roleId == 2 && strpos($role, 'expert') === false) {
// an `expert` is trying to access route that can't be accessed
return redirect('/expert-dashboard');
} // and so on...
}
You'd define routes as:
Route::group(['middleware' => ['new_middleware:expert,user' ]], function () {
Route::post('/showForm','UserController#showFormFilled');
});
Hope this helps.

How do I validate User role on Laravel 5.8s Built in Authentication?

I've a User Role column on my User's table.
stands for Super Admin,
stands for other users
I've checked a lot of Laravel Tutorials and none of them has helped me about solving this issue.
I've found ways like replacing the whole Laravel's Login Controller and replacing Authenticate Users trait with ours own. I want to solve my problem with minimal code change. Is it possible?
How do I implement it with minimal code changes in this Trait method?
public function login(Request $request)
{
$this->validateLogin($request);
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
You could do something as supersimple as adding a isSuperAdmin function to the User model. After logging in you just call this function on the user whenever you need to check.
In model User.php
public function isSuperAdmin()
{
return $this->user_role == 1;
}
Then you could also make a middleware that's using this function.
php artisan make:middleware SuperAdmin
In the handle function of this middleware (app/http/middleware/SuperAdmin.php):
public function handle($request, Closure $next)
{
if (Auth::check() && Auth::user()->isSuperAdmin()) {
return $next($request);
}
return redirect('some-route-for-unauthorized-users');
}
Then in your routes (probably web.php), you can use this middleware to protect routes:
Route::group(['middleware' => ['auth', 'superadmin']], function () {
... put protected routes here ...
});
Solution
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct() {
$this->middleware('guest')->except('logout');
}
protected function credentials(Request $request)
{
$credentials = $request->only($this->username(), 'password');
$credentials['role'] = '1';
return $credentials;
}

Laravel 5.4 Route [login] not defined

Hi I have following route and constructor in my controller i want to check if user is authenticated or not if not then redirect to /warehouse/login page. but for some reasons i am getting Route [login] not defined error.
I am migrating my functions from Laravel 4.2 to Laravel 5.4
Constructor:
public function __construct()
{
$this->middleware('auth');
$this->middleware(function ($request, $next) {
if (!Auth::check()) {
$url = URL::current();
$routeName = Route::currentRouteName();
if ($routeName != "AdminLogin" && $routeName != 'admin') {
Session::put('pre_admin_login_url', $url);
}
return redirect('/warehouse/login');
}
return $next($request);
}, array('except' => array('WarehouseAdminLogin', 'WarehouseAdminVerify')));
}
Routes:
Route::get('/warehouse', 'WarehouseController#index');
Route::get('/warehouse/login', array('as' => 'WarehouseAdminLogin', 'uses' => 'WarehouseController#login'));
You didnt define your login function.
make a function
public function login()
{'your code'}
in your WarehouseController
Edited: the problem is that you have not a route named login. This error is caused by:
$this->middleware('auth');
because this code in the auth middleware:
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
So what to do is remove auth middleware and try again or make a route with login name.

Resources