Listing middleware in kernel.php - laravel

I have an admin middlware AdminMiddleware.php
public function handle($request, Closure $next, $guard = null)
{
if(Auth::check())
{
if($request->user()->is_admin==1)
{
return $next($request);
}
return redirect('/login');
}
else
{
return redirect('/login');
}
}
And i have some routes under adminmiddleware:
Route::group(['middleware' => ['App\Http\Middleware\Adminmiddleware']], function () {
//admin routes
});
Working properly. And i'm litte confused on Registering middleware? Why should i register. Only for alias or something more effective?

For $routeMiddleware and $middlewareGroups, they are mostly for aliasing. As you mentioned, you can don't register it and use it just fine in your route file.
It's more on conveniency for your to swap the implementation shall you need to.
IMO, register it so that you can swap the middleware implementation at any point of time without going into your route configuration file to change it - which is more error prone than one central location to change.

Registering middleware is loading the class with each request automatically. You're telling Laravel to load and register it, so you could use it in routes and controllers without initializing it manually. Same with console commands, service providers etc. You must register before using them.
If you want a middleware to run during every HTTP request to your application, simply list the middleware class in the $middleware property of your app/Http/Kernel.php class.

Related

Change LogIn route

I am working in Laravel auth application and when my user is log out I want to redirect it to custom static page and from there I want to redirect to login page again by clicking button on that page.
For example when user is trying to access some particular route, and he is unauthorized then I want to redirect with satatic.blade.php and from there I want to redirect it to log in page, How can I make it happen?
As you didn't mention which Laravel version you are using and which scaffolding you are using, I am assuming you are using Laravel 5.5/6 with LaravelUI/default auth scaffolding.
You should have App\\Http\\Controllers\\Auth namespace where you kept all auth related controller.
You should have one LoginController.php which contains all default login behavior inside AuthenticatesUsers trait. We should override the login method inside our controller.
Copy this code to your LoginController class to do so.
public function login(Request $request)
{
$this->validateLogin($request);
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
// Here is our custom logic check occurs before login
if ($this->userIsnotAuthorized()) { // All your logic checks are inside 'userIsnotAuthorized()' method. Use any function or static check here
return redirect()->to('/static/page'); // Also can use route name / url
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
EDIT #1
If you want to have the same check for all protected routes, you should generate a middleware with php artisan make:middleware CheckResourceAccessMiddleware and use the same in your route.
In CheckResourceAccessMiddleware's handle method
// Here is our custom logic check occurs before login
if ($this->userIsnotAuthorized()) { // All your logic checks are inside 'userIsnotAuthorized()' method. Use any function or static check here
return redirect()->to('/static/page'); // redirect to static page which indicates unauthorized user note
}
return $next($request); // proceed to your page as user is authorized
to register the middleware edit your app/Http/Kernel.php and add this line to $routeMiddleware array
protected $routeMiddleware = [
...
'resource_access' => \App\Http\Middleware\CheckResourceAccessMiddleware::class,
];
After this step., you can use the middleware in any routes you want to protect
Route::get('/protected', [Controller::class, 'method'])->middleware('resource_access');
OR
// Middleware will be applied to all routes inside it
Route::middleware('resource_access')->group(function () {
Route::get('/protected', [Controller::class, 'method']);
// all other protected routes will be here
});
I found different approaches for this problem, Later I Found the best solution, as mention below,
In App\Middlewear\Authenticate.php, I have to change from return route('login');
to return route('my_custom_page_route');
From my custom page I can redirect it to auth login page easily.
Thank you everyone who suggest the best solutions.

Laravel Custom Middleware

I am trying to achieve this using middleware
web.php
Route::get('/test', 'TestController#index')->middleware('TestLogin');
redirect to /test if session is found
Route::get('/test1', 'TestController#index1')->middleware('TestLogin');
redirect to test1 if session is set
Middleware -TestLogin
public function handle($request, Closure $next)`
{
if($request->session()->get('Username'))
{
return redirect()->route(\);
// what to write here to redirect to the path its being called from
}
return redirect()->route('login');
}
don't want to use default auth middleware
Your middleware is suppose to check the login (session), if it is not found then redirect to login page otherwise it should pass the request. Something like this:
public function handle($request, Closure $next)
{
// No login session, redirect
if(!$request->session()->get('Username'))
{
return redirect()->route('login');
}
// Pass the request down the rest of pipeline
return $next($request);
}
You should consider to use built in authentication system in Laravel itself, it will save you lots of code and you can be sure the auth is handled correctly in security point of view.

Auth::user() is null in new route

i'm using laravel 6 and have 2 route in my app; index and dashboard.
My routes/web is:
Auth::routes();
Route::middleware(['auth'])->group(function () {
Route::get('/index', 'todoApp\TodoController#index')->name('index');
Route::get('/dashboard', 'todoApp\Dashboard#dashboard')->name('dashboard');
});
i added dashboard route recently.
Auth::user() is null when i dump it in dashboard route but doesn't in index. What's the
Your Controller is instantiated before the middleware stack has ran; this is how Laravel can know what middleware you have set via the constructor. Because of this you will not have access to the authenticated user or sessions at this point. Ex:
public function __construct()
{
$this->user = Auth::user(); // will always be null
}
If you need to assign such a variable or access this type of information you would need to use a controller middleware which will run in the stack after the StartSession middleware:
public function __construct()
{
$this->middleware(function ($request, $next) {
// this is getting executed later after the other middleware has ran
$this->user = Auth::user();
return $next($request);
});
}
When the dashboard method is called, the middleware stack has already passed the Request all the way through to the end of the stack so all the middleware needed for Auth to be functioning and available has already ran at that point which is why you have access to Auth::user() there.
I think that this has something to do with the 'web' middleware. If you take a look into the Kernel.php (In app\Http) you will find the web middleware group.
This will show you that it actually calls a middleware called StartSession. Based on your route file (where web is not included as a middleware) I would think that you don't have a session in your Controller and there for no access to it.
I don't quite understand why this only happens in your /dashboard route, because the issue should also be in your /index route (unless you added the web middleware somewhere in your TodoController).
I think that this should do the trick:
Route::middleware(['web', 'auth'])->group(function () {
Route::get('/index', 'todoApp\TodoController#index')->name('index');
Route::get('/dashboard', 'todoApp\Dashboard#dashboard')->name('dashboard');
});
If you fire php artisan make:auth command.
It's doesn't matter where you define because of it's only define auth route
Route::middleware(['auth'])->group(function () {
Route::get('/index', 'todoApp\TodoController#index')->name('index');
Route::get('/dashboard', 'todoApp\Dashboard#dashboard')->name('dashboard');
});
Auth::routes();

Laravel preventing user from accessing other users resource **url

I am passing a specific resource in the url, for ex.
https://www.example.com/{companyID}
And in the controller I can access the resource by
public function index($companyID)
{
// Code Here
}
I need to block users from changing the url and accessing other companyIDs from the system. Currently its open and is a security risk. I checked out Laravel Gate and Policy's but fail to see how this could be implemented for my case.
What I am really looking for is something in the AuthServiceProvider boot method that can check if the user really is the owner of the resource before continuing with the code.
Any help?
As mentioned before, you can do that by creating a Middleware that checks if your resource should be available to the logged in user.
See some details about middleware here
First, create a Middleware via php artisan, like this
php artisan make:middleware AuthResource
Next, add it to your App\Http\Kernel.php
protected $routeMiddleware = [
...
'AuthResource' => \App\Http\Middleware\AuthResource::class,
];
In your routes, you can now do the following:
Route::get('{companyID}', ['uses' => CompanyController#index, 'middleware' => 'AuthResource']);
That way, your AuthResource middleware is used whenenver the route is called.
In your App\Http\Middleware\AuthResource.php you have to change the code from
public function handle($request, Closure $next)
{
return $next($request);
}
to something that checks if the resource is available to the currently logged in user.
I assume that your companies table has a field user_id, which links the Company to a User. If your data structure is different, you need to change the code accordingly.
public function handle($request, Closure $next)
{
if ($request->route('companyID')) {
$company = Company::find($request->route('companyID'));
if ($company && $company->user_id != auth()->user()->id) {
return redirect('/');
}
}
return $next($request);
}
That way we check if the a route parameter with the name companyID exists, and if it does we check if it is available to the currently logged in user. If no companyID parameter is available, the page can be loaded without any restrictions.
That way you can copy/paste the code within the middleware for any parameters so that the middleware does work for multiple resources (not only companies).
This is can be done easily by middleware. But I’ll do this in more understandable way.
I assume that your user has one to one relationship with company.
So first create the relationship,
In your User model,
Public function company() {
return $this->hasOne(‘App\Company’);
}
Company model
Public function user(){
return $this->belongsTo(‘App\User’);
}
So, now make Authenticate by running php artisan make:auth . more details on Authenticate
And now in your controller,
public function index($companyID)
{
$current_user = Auth::user();
$user_company = $current_user->company; // get the current user's company details
If($companyID == $user_company->id){
// do something
}
}

$request->route() is null in Middleware, how can I filter by route parameters?

Laravel 5.1 deprecates Route::filter() and other related functions, claiming in the docs that:
Route filters have been deprecated in preference of middleware.
But if your route filter accesses route parameters, how can you replace this with middleware, since the $request->route() is null in middleware?
Route::filter('foo', function($route, $request) {
if ($route->parameter('bar') > 1000) {
return Redirect::route('large-bars');
}
});
The closest I can see is something like
class FooMiddleware {
public function handle($request, Closure $next)
{
// Note that $request->route() is null here, as the request
// hasn't been handled by Laravel yet.
if ($request->segment(4) > 1000) { // ewww...
return Redirect::route('large-bars');
}
return $next($request);
}
}
but this is obviously much more brittle than referring to the parameter by name. What am I missing here? Thanks!
$request->route() is only null for global middleware registered in App\Http\Kernel::$middleware. To have access to the current route, instead you must register your middleware in Kernel::$routeMiddleware:
protected $routeMiddleware = [
...,
'foo' => FooMiddleware::class,
];
Proposals to change this behavior have been rejected by the Laravel maintainers due to architectural concerns.

Resources