Using multiple authentication middlewares for one route - php

I have a requirement where there is an API method (guarded by the well-known package tymon/jwt-auth) and I need to also be able to access it using the basic session based web middleware.
I don't want to repeat the route in both api.php and web.php even though that would totally work.
I tried adding both to the route but they simply don't work, like: ['auth:api', 'web']
I also tried creating a new middleware with the intention of checking both api and web like so:
class CombinedAuth
{
public function handle($request, Closure $next)
{
$web = Auth::guard('web')->user();
if ($web) {
return $next($request);
}
$api = Auth::guard('api')->user();
if ($api) {
return $next($request);
}
if(!$web && !$api) {
throw new AuthorizationException;
}
}
}
and that also doesn't work. The api middleware works fine but the web middleware doesn't and it always signs me out and redirects to the login page.
So Is there a neat way of protecting a route with api and web middlewares at the same time in Laravel 5.8?

You can use 'auth:api,web' to check for multiple guards.

Using multiple can middleware calls in Laravel 9 route;
<?php
Route::get('/', function () {
return view('money');
})
->middleware([
'can:manage,App\Models\Payment',
'can:manage,App\Models\Withdraw',
]);
?>

Related

Laravel: Checking if user has permission

I'm writing a server based solution. In database there are many users with different permissions and I have to check if they have permission to access module they are trying to.
In every Controller I have included something like:
protected $module = "moduleName";
I tried to solve it like:
function __construct()
{
$perm = session()->get('perm');
if (!isset($perm[$this->module]) || !$perm[$this->module]) {
Session::flash('message_error', "<span class='glyphicon glyphicon-warning-sign'></span> Access denined!");
return back();
}
}
It shows the message but it still displays the page not redirects back.
As you see I'm reading permissions from session and modules name is saved in controller so I don't think this could be solved by middleware unless I'm making middleware for each module (I'm talking about 30 modules).
Thanks for taking the time to read this
Middleware actually solved this.
Route:
Route::group(['middleware' => 'module:moduleName'], function () {
// Routes...
});
Custom middleware:
public function handle($request, Closure $next, $module)
{
$perm = session()->get('perm');
if (!isset($perm[$module]) || !$perm[$module]) {
Session::flash('message_error', "<span class='glyphicon glyphicon-warning-sign'></span> Access denined!");
return redirect()->back();
}
return $next($request);
}
Also I'll mention that Route groups can be nested. So you can wrap multiple groups with something like auth middleware as well
There is a very easy fix to your code, you forgot the define the redirect, so instead of using
return back();
use
return redirect()->back();
This will do the redirect.
There is also a mistake in your reasoning, you could and probably should use middleware.
Middleware does have access to the user, session and can be passed parameters. These are the necessary requirements for your system.
You can also assign middleware on a controller basis.

Laravel middleware authentication

Currently to add authentication I use this in my routes file:
Route::middleware(['auth'])->group(function () {
});
But I want to also check for different routes if the user is an admin, so currently I do this and have a custom middleware file:
Route::middleware(['auth', 'admin'])->group(function () {
});
//
<?php
namespace App\Http\Middleware;
use Closure;
class Admin {
public function handle($request, Closure $next)
{
if ( Auth::check() && Auth::user()->isAdmin() )
{
return $next($request);
}
return redirect('dashboard');
}
}
This all works fine, but I noticed with the api middleware it uses this:
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Questions
How can I make a namespaced auth middleware like the api one 'auth:admin'
Where is the file located that sets the 'auth:api' middleware, I could not find it anywhere in the app folder
Is there any other ways to do multiple auth like editing the file config/auth.php and then separating the users between two tables, one for admins and one for other users.
auth:api is actually the basic auth middleware with the string api as a parameter. This means the user is authenticated using the api authentication guard
You could use auth:admin out of the box if you added a custom authentication guard for the admins.
The auth middleware accepts one parameters which is the guard(s) to use. As you can see in Illuminate\Auth\Middleware\Authenticate middleware.
You can add custom auth guards. So you can create auth:admin if you'd like. But I do think it's perfectly fine to use one middleware to verify that the user is who he is (authentication) and a second one to verify that the user is allowed to visit the page he/she wants to visit (authorization).

laravel routes , how to redirect if statement , routes.php

i have in routes.php user and admin routes , how to can access admin routes just if Session::get('admin')==1 ?
enter image description here
You need to define a middleware, for example:
namespace App\Http\Middleware;
use Closure;
class CheckAge
{
public function handle($request, Closure $next)
{
if (!session()->has('admin') || session('admin') != 1) {
return redirect('/');
}
return $next($request);
}
}
Register it and apply it to routes you want to protect.
Doesn't look like you have a specific problems in terms of code, so I'm just going to point you to the documentation on Middleware.
Middleware get's executed before it reaches the controller, therefore you can apply your logic there, simply create a new middleware, add an if statement but instead of returning $next return response() with your appropriate response should the middleware fail.
Laravel Docs

How can we redirect a page to another if a session is not found using route in Laravel 5.3

I am using a session separately other than the default authentication sessions. If an user try to access my secured page, he should have the session set. If anyone without that session try to access means, they will be redirected to error page. I am using Laravel 5.3
The user can view the below two pages only if the session variable named 'secured_user' is set. Otherwise they will be redirect to the error page
Route::get('/secured-page1', 'ValidationController#CheckSecuredLogin_1');
Route::get('/secured-page2', 'ValidationController#CheckSecuredLogin_2');
The best option would be a policy.
You can create certain constrains and couple it with your models. Policies are especially suitable for changing your logic later on.
See here: Create Policy
Within you PagesPolicy, you can add this function:
public function before(User $user, $ability)
{
if ($user->isSuperAdmin()) {
return true;
}
}
public function seeSecurePage(User $user)
{
// Your custom Code and session handling
if(session("secured_user")) return true;
return false;
}
and in your controller.
$user->can("seeSecurePage","Pages");
If "can" fails, it will automatically redirect to error 403.
P.S.: Another possibility are Gates
You should use Laravel Middlewares to achieve this, I think middlewares are made for the work you need:
First create a new middleware by running the artisan command:
php artisan make:middleware CheckSesison
Then the CheckSession would look like this:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckSession
{
public function handle($request, Closure $next)
{
if ($session_value != 'YOUR_DESIRED_VALUE') {
return redirect('home');
}
return $next($request);
}
}
Now in your routes file you can use laravel's route middleware() method to implement it like this:
Route::get('/secured-page1', 'ValidationController#CheckSecuredLogin_1')
->middleware(CheckSession::class);
Hope this helps!
In addition to the awnser above, you could also use middleware that's used on the routes and even group them if required. It is a simple, quick and clean solution. Inside the middelware you simple check if the session you require is there and depending on the result you take any action necessary.
Laravel middleware docs

Customizing auth middleware - Laravel 5

The delivered auth middleware that comes with Laravel 5 is great for user-only routes and controllers, however I want to add the ability to also check if the user is an administrator.
Currently, in my controllers, I have this for every class:
if (Auth::user()->level <= 1) {
// admin can do these actions
} else {
// redirect
}
It's very redundant and I'd like to look at what my options are. Since I want to retain the original auth middleware for user authentication, should I be building a new one for administrator authentication, or can I make some simple change in the original auth middleware that can account for my code above?
Middleware in Laravel 5.0 do not support arguments (this will be added in the upcoming 5.1 release).
Your options are to either create a separate middleware for this, or use route filters.
You can create a route filter by putting this in your RouteServiceProvider's boot method:
$router->filter('userLevel', function($route, $request, $level)
{
$user = auth()->user();
if ( ! $user || $user->level > $level)
{
return response('Unauthorized', 401);
}
});
Then use that filter in your routes:
Route::group(['before' => 'userLevel:1'], function($router)
{
// define routes...
});

Categories