Get Requested middleware list from $request? - laravel

In my project created with Laravel 8 with vue+ inertia + fortify package, I use two guards one for normal users and one for admins. but there only have one login view redirect.
I just want to show different login to normal users and another login to admins. it should detect by middleware used in the route. I can filter it, if I can get the requested guard name from there.
Here is my example route:
<?php
//'auth:users' is normal users guard
Route::group(['middleware' => 'auth:users'], function () {
Route::prefix('/account')->name('account.')->group(function () {
Route::get('/', [AccountController::class, 'index'])->name('index');
});});
//'auth:web' is admin users guard
Route::group(['middleware' => 'auth:web'], function () {
Route::prefix('/admin')->name('admin.')->group(function () {
Route::prefix('/account')->name('account.')->group(function () {
Route::get('/', [AdminAccountController::class, 'index'])->name('index');
});
});
});
auth middleware:
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* #param \Illuminate\Http\Request $request
* #return string|null
*/
protected function redirectTo($request)
{
// both request coming to here i want get middlware name from here
// if('auth:web'){
//redirect to adimin login
// }else{
//redirect to userlogin
//}
if (! $request->expectsJson()) {
return route('admin.login');
}
}
}

You can get a list of all middleware used for the current route using request()->route()->computedMiddleware so your code would be:
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* #param \Illuminate\Http\Request $request
* #return string|null
*/
protected function redirectTo($request)
{
if ($request->route() && in_array('auth:web', $request->route()->computedMiddleware??[]) {
// redirect to admin login
} else {
// redirect to admin login
}
if (! $request->expectsJson()) {
return route('admin.login');
}
}
}

Related

laravel breeze force the user to enter password again after session expired

I am using laravel 9.0 with breeze for authentication
how can I ask the user to reenter the credentials after the session is expired
You have many choices but if you want to check session validity on every request then you can use a middleware.
In your command console run:
php artisan make:middleware CheckSession
CheckSession.php
<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
use Session;
class CheckSession
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::user() && time() - Session::activity()) < (Config::get('session.lifetime') * 60) {
return $next($request);
}
return redirect('/login')->with('error','Session expired! Please login again.');
}
}
app/Http/Kernel.php
add this line to the protected $routeMiddleware array:
'sessionChecker' => \App\Http\Middleware\CheckSession::class,
routes/web.php
add your route middleware to every route that you want to check session validity for. for eaxample you have below route:
Route::group(['middleware' => ['auth']], function () {
Route::get('/products', 'ProductController#index')->name('products');
});
should be:
Route::group(['middleware' => ['auth', 'sessionChecker']], function () {
Route::get('/products', 'ProductController#index')->name('products');
});

Laravel group multiple Middleware

In my application I have three user roles:
user
editor
admin
When editor logs into the admin section, some of the sections are hidden (users manage, system information etc.) and of course, the admin can see everything.
So, for this purpose I've created two middleware: Admin and Editor. This is the code.
Admin middleware.
<?php
namespace App\Http\Middleware;
use Illuminate\Support\Facades\Auth;
use Closure;
class Admin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::check()) {
if(Auth::user()->role_id == 3) {
return $next($request);
}
}
return redirect('/');
}
}
Editor middleware:
<?php
namespace App\Http\Middleware;
use Illuminate\Support\Facades\Auth;
use Closure;
class Editor
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::check()) {
if(Auth::user()->role_id == 2) {
return $next($request);
}
}
return redirect('/');
}
}
Here's the part of the Kernel:
protected $routeMiddleware = [
'admin' => \App\Http\Middleware\Admin::class,
'editor' => \App\Http\Middleware\Editor::class,
];
Now I'm trying to build the routes that will be available to those user roles.
If I do it only for the admin or the editor, it works fine, but when I combine them, the one user can login and the other cannot.
Here's the code only for the admin and it works fine.
Route::middleware('admin')->group(function(){
Route::get('/admin', 'PagesController#adminIndex');
Route::resource('/admin/pages', 'PagesController');
Route::resource('/admin/news', 'NewsController');
Route::resource('/admin/users', 'UsersController');
...
});
I've tried to combine them with this code, but it's not working (cannot login into the admin section at all):
Route::middleware(['admin', 'editor'])->group(function(){
Route::get('/admin', 'PagesController#adminIndex');
Route::resource('/admin/pages', 'PagesController');
Route::resource('/admin/news', 'NewsController');
Route::resource('/admin/users', 'UsersController');
...
});
How can I solve this problem?
P.S. Later I want to build a logic for the User role too, so there's must a way to combine the routes.
You can solve the problem with help of Middleware Parameters and instead of several middlewares for each role use only one universal middleware with roles as parameters.
For example:
protected $routeMiddleware = [
'checkRole' => \App\Http\Middleware\CheckRole::class,
];
Middleware:
<?php
namespace App\Http\Middleware;
use Illuminate\Support\Facades\Auth;
use Closure;
class CheckRole
{
public function handle($request, Closure $next, ...$roles)
{
$roleIds = ['user' => 1, 'editor' => 2, 'admin' => 3];
$allowedRoleIds = [];
foreach ($roles as $role)
{
if(isset($roleIds[$role]))
{
$allowedRoleIds[] = $roleIds[$role];
}
}
$allowedRoleIds = array_unique($allowedRoleIds);
if(Auth::check()) {
if(in_array(Auth::user()->role_id, $allowedRoleIds)) {
return $next($request);
}
}
return redirect('/');
}
}
Routes:
Route::middleware(['checkRole:admin,editor'])->group(function(){
//Your routes
});
It should be like below.
Route::middleware(['auth'])->group(function(){
//common routes will goes here
Route::middleware(['admin'])->group(function(){//admin routes will goes here
Route::get('/admin', 'PagesController#adminIndex');
Route::resource('/admin/pages', 'PagesController');
Route::resource('/admin/news', 'NewsController');
Route::resource('/admin/users', 'UsersController');
});
Route::middleware(['editor'])->group(function(){
//editor routes goes here.
});
});
The problem is that your middleware(['admin', 'editor']) is checking the both roles i.e. admin,editor for user and you have only one role for user. That is reason why it is not working
There are great packages out there for managing the user roles which are easy to use . I suggest you to use Spatie Laravel Permission if you want tutorials on it watch Bitfumes Video

Laravel redirecting authenticated users to login route

When I try to access any route under the auth middleware I get redirected to a login route.
Route::group(['middleware' => 'auth'], function () {
Route::get('area-cliente/resumo', 'AreaClienteController#resumo')->name('area_cliente_resumo');
});
this is my authenticate middleware
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* #param \Illuminate\Http\Request $request
* #return string
*/
protected function redirectTo($request)
{
if(Auth::guard('cliente')->guest())
{
return route('registrar');
}
return next($request);
}
}
I cannot see where the code that is redirecting to a login route is located and I don't know why either, since the user is apparently logged using the code below;
public function logar(Request $request) {
$credenciais = [
"email" => $request->email,
"senha" => $request->senha
];
$results = auth()->guard('cliente')->login(Cliente::find(1));
if(auth()->guard('cliente')->check()){
//I am able to echo the name of the user
//echo auth()->guard('cliente')->user()->name
return redirect()->route('home');
}
else{
echo "no";
}
}
I've also tried to clean (remove all functions) of the RedirectIfAuthenticated and authenticate middleware but the behavior of the application doesn't change, I still being redirected to a login page on the routes under the auth middleware.

how to use session in middleware to always check that a user is logged in or not

i am new in laravel . i am trying to check if user is logged in or guest . i create a middleware named (checkUserLogin) and my code is:
namespace App\Http\Middleware;
use Auth;
use Closure;
use App\Http\Controllers\Controller;
use session;
class checkUserLogin
{
public function handle($request, Closure $next)
{
if (session()->get('email') != ''){
// redirected to dashboard.
}else{
// redirect to login page.
}
return $next($request);
}
}`
in my controller and blade template session()->get('email') works fine and i get the email of the user who logged in but in middleware if i try to print the session()->get('email') then a blank screen appears.
Use The Tools Given To You
Read the documentation and learn about Retrieving The Authenticated User. You will see that you can retrieve the logged in user with $request->user()
Look at the code for the included middleware RedirectIfAuthenticated. You will see that you can check if a user is logged in with Auth::guard($guard)->check()
Example Middleware Code
namespace App\Http\Middleware;
use Auth;
use Closure;
class checkUserLogin
{
public function handle($request, Closure $next)
{
if ( $request->user() ){
// user is logged in
} else {
// user is not logged in
}
return $next($request);
}
}
Some Thoughts
If your goal is for any visitor to see the route, but to show logged in visitors a different portion of content than you would show guests, this is simple to do within the Controller. For example, it is common to show a link to "Login" when the user is not logged in. When the user is logged in it is common to show the user account menu instead.
you can use this code.
Auth::user();
this will check automatically
just replace the below lines of code with yours... hope will work...
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class checkUserLogin
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $user;
/**
* Create a new middleware instance.
*
* #param Guard $user
* #return void
*/
public function __construct(Guard $user)
{
$this->user = $user;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->user->guest())
{
if ($request->ajax())
{
return response('Unauthorized.', 401);
}
else
{
return redirect()->guest('login');
}
}
return $next($request);
}
}

Make session expiration redirect back to login?

When user logs in and is authenticated, I use Auth::user()->username; to show username of user on dashboard. However, for some reason when session expires the class Auth doesn't seem to work and dashboard page throws error as trying to get property of non-object for Auth::user()->username;. How can I redirect the user back to the login page when he clicks any link or refreshes the page after the session has expired?
I tried the Authenticate.php middleware but it always redirects back to login page,whatever you put the credentials either correct or incorrect.However,when I don't use this middleware it logins the user.Am I missing something?
Route.php
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/
/*
Actions Handled By Resource Controller
Verb Path Action Route Name
GET /photo index photo.index
GET /photo/create create photo.create
POST /photo store photo.store
GET /photo/{photo} show photo.show
GET /photo/{photo}/edit edit photo.edit
PUT/PATCH /photo/{photo} update photo.update
DELETE /photo/{photo} destroy photo.destroy
Adding Additional Routes To Resource Controllers
If it becomes necessary to add additional routes to a resource controller beyond the default resource routes, you should define those routes before your call to Route::resource:
Route::get('photos/popular', 'PhotoController#method');
Route::resource('photos', 'PhotoController');
*/
// Display all SQL executed in Eloquent
// Event::listen('illuminate.query', function($query)
// {
// var_dump($query);
// });
define('ADMIN','admin');
define('SITE','site');
Route::group(['namespace' => ADMIN], function () {
Route::get('/','UserController#showLogin');
});
////////////////////////////////////Routes for backend///////////////////////////////////////////////////
Route::group(['prefix' => ADMIN,'middleware' => 'auth'], function () {
Route::group(['namespace' => ADMIN], function () {
//Route::get('/','EshopController#products');
//sumit routes for user registration
//Route::resource('users','UserController');
Route::get('/users/destroy/{id}','UserController#destroy');
Route::get('UserProf','UserController#userProf');
Route::get('users','UserController#index');
Route::get('/users/create','UserController#create');
Route::get('/users/adminEdit/{id}','UserController#adminEdit');
Route::post('/users/adminUpdate','UserController#adminUpdate');
Route::post('/users/store','UserController#store');
Route::get('/users/edit/{id}','UserController#edit');
Route::post('/users/update/{id}','UserController#update');
//airlines route
Route::get('airlines','AirlinesController#index');
Route::get('/airlines/create','AirlinesController#create');
Route::post('/airlines/store','AirlinesController#store');
Route::get('/airlines/edit/{id}','AirlinesController#edit');
Route::post('/airlines/update','AirlinesController#update');
Route::get('/airlines/destroy/{id}','AirlinesController#destroy');
//end sumit routes
//flight routes
Route::get('flights','FlightController#index');
Route::get('showFlightBook','FlightController#showFlightBook');
Route::get('flights/create','FlightController#create');
Route::post('flights/store','FlightController#store');
Route::get('flights/book','FlightController#book');
Route::get('flights/edit/{id}','FlightController#edit');
Route::post('flights/update','FlightController#update');
Route::get('flights/destroy/{id}','FlightController#destroy');
//Route::resource('flight','FlightController');
//hotels route
Route::get('hotels','HotelsController#index');
Route::get('/hotels/create','HotelsController#create');
Route::post('/hotels/store','HotelsController#store');
Route::get('/hotels/edit/{id}','HotelsController#edit');
Route::post('/hotels/update','HotelsController#update');
Route::get('/hotels/destroy/{id}','HotelsController#destroy');
//end sumit routes
//book-hotel routes
Route::get('hotel-book','HotelBookController#index');
Route::get('showHotelBook','HotelBookController#showHotelBook');
Route::get('hotel-book/create','HotelBookController#create');
Route::post('hotel-book/store','HotelBookController#store');
Route::get('hotel-book/book','HotelBookController#book');
Route::get('hotel-book/edit/{id}','HotelBookController#edit');
Route::post('hotel-book/update','HotelBookController#update');
Route::get('hotel-book/destroy/{id}','HotelBookController#destroy');
//Route::resource('hotel','HotelController');
//close flight routes
//for admin login
//Route::get('initlogin','UserController#lgnPage');
Route::get('login','UserController#showLogin');
// Route::get('privilegeLogin','UserController#privilegeLogin');
// Route::post('privilegeCheck','UserController#privilegeCheck');
Route::post('login','UserController#doLogin');
Route::get('/dashboard','DashController#index');
Route::get('logout','UserController#doLogout');
//user login
//Route::get('userLogin','UserController#showUserLogin');
//Route::post('userLogin','UserController#doUserLogin');
Route::get('/userDashboard','DashController#userIndex');
Route::get('Logout','UserController#doUserLogout');
//password reset
Route::get('forget-pass','UserController#showReset');
//Route::get('home', 'PassResetEmailController#index');
});
});
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
Authenticate.php:
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class Authenticate {
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->guest())
{
if ($request->ajax())
{
return response('Unauthorized.', 401);
}
else
{
// return redirect()->guest('auth/login');
return redirect()->guest('/');
}
}
return $next($request);
}
}
All you have to do is just put this constructor at the top of the controller for your dashboard. It seems Laravel has a middleware that handles this already. At least I can confirm from 5.4 and up.
public function __construct()
{
$this->middleware('auth');
}
If the session expires then you can redirect to log in like as
open this file app/Exceptions/Handler.php add this code
public function render($request, Exception $exception)
{
if ($exception instanceof \Illuminate\Session\TokenMismatchException) {
return redirect('/login');
}
return parent::render($request, $exception);
}
If you want a middleware to be run during every HTTP request to your application, simply list the middleware class in the $middleware property of your app/Http/Kernel.php class.
So, to protect every route from being accessed without authentication do this
protected $middleware = [
'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
'Illuminate\Cookie\Middleware\EncryptCookies',
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
'App\Http\Middleware\VerifyCsrfToken',
'App\Http\Middleware\Authenticate',// add this line according to your namespace
];
it will redirect the user if not logged in. UPDATE Keep in mind that adding auth middleware as global will create redirect loop so avoid it.
Or if you want specific routes to be protected then attach the middleware auth to that route
Route::get('admin/profile', ['middleware' => 'auth', function () {
//
}]);
I think you are not attaching the auth middleware to your routes.
Create a middleware like this
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class Authenticate
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
}
return $next($request);
}
}
Then Group the routes and protect them like this
Route::group(['middleware' => 'auth'], function()
{
Route::get();
Route::get();
Route::get();
Route::get();
}
Offcourse, in the routes you have to specify your links etc, it will only allow the user when he is authenticated and if not then login page will be shown
To make session redirect to your login just add ->middleware('auth') in your router files as shown below I am using laravel 5.3
Ex:
Route::post('controllerName','folderName\fileName#fnNmae')->middleware('auth');
Or visit https://laravel.com/docs/5.3/authentication

Resources