Custom Middleware - 'Too Many Redirects' - Laravel - php

I want to create a custom middleware that only if the user is authenticated and the email is a certain email to access the /admin page.
Although, when I specify my custom route and then a redirect it always says too many redirects..
Short Explanation.
User Logs in -> redirected to /home. (Works)
If user tries to access /admin and their email isn't like the one specified in the middleware, redirect to /home.
If its true, let them in /admin
My middleware is called 'admin.verify'
Routes File:
Route::get('/admin', 'AdminController#index')->name('admin.index');
AdminController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AdminController extends Controller
{
public function __construct(){
$this->middleware(['auth', 'admin.verify']);
}
public function index(){
return view('admin.test');
}
}
Middleware:
public function handle($request, Closure $next)
{
if (Auth::check() && Auth::User()->email == 'Tester#gmail.com') {
return $next($request);
} else {
return redirect()->route('home');
}
My Home Route:
GET|HEAD | home | home| App\Http\Controllers\HomeController#index | web,auth
Home Controller:
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return view('home');
}
}

Use $this->middleware ('admin.verify') instead of $this->middleware(['auth, admin.verify]');. You are getting too many redirects error because both the admin middleware and the constructor are checking if the user is authenticated.

The problem is that when you access home route auth.verify method is called and when it fails it is redirected to home itself creating a loop hence too many redirects error.
Change else condition in auth.verify middleware to redirect to another page like /login

Related

Protect Route in Laravel 9 Based on User Column Value

I have a column in my User table named role with 2 possible values--"Admin" and
"Driver".
All my crud routes are protected with Auth middleware, but I'd like to further secure a few of those routes.
For example I'd like to have the "Create" routes only accessible by Users with the role column equalling "Admin". I wasn't sure how to go about this, so I can't provide examples of what I've tried.
web.php
...
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/users', App\Http\Livewire\User\Index::class)->name('users.index');
Route::get('/user/{user}/edit', App\Http\Livewire\User\Edit::class)->name('user.edit');
/* This is the route I want to protect to just "Admin" role */
Route::get('/user/create', App\Http\Livewire\User\Create::class)->name('user.create');
...
You can create a middleware with the artisan command
php artisan make:middleware IsAdminMiddleware
Then add something like this in the handle function of your middleware.
public function handle(Request $request, Closure $next)
{
// This validation assumes you can access role from User Model
if ($request->user()->role != "Admin") {
return response()->json(['error' => 'you are not an admin!'], 403);
}
return $next($request);
}
Finally add the middleware on your Routes
Route::get('/user/create', App\Http\Livewire\User\Create::class)
->middleware(IsAdminMiddleware::class) // <<----
->name('user.create');
For more info refer to middleware the docs at laravel.
You can use authorization in laravel for your case
in laravel you can use gate or policy for further feature
https://laravel.com/docs/9.x/authorization
Gate
define gate in App\Providers\AuthServiceProvider on method boot
use Illuminate\Support\Facades\Gate;
use Illuminate\Auth\Access\Response;
use App\Models\User;
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
Gate::define('create', function (User $user) {
return ($user->role == 'Admin')
? Response::allow()
: Response::deny('You must be an administrator.');
});
}
On your controller
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
class CreateController extends Controller
{
public function create(Request $request)
{
$user = Auth::user();
if (Gate::allows('create', $user)) {
//create
}
}
}

How to redirect non-authenticated users to login view

I'm making an application which requires a user and password for access. Every user should face the login view. Currently, writing the URL manually, I can access all the routes without login. What I want is to redirect every unauthenticated user to the login view, so that they can't see anything else until they log in.
LoginController
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
public function redirectTo() {
$isAuth = Auth::check();
if ($isAuth) {
return redirect('dashboard');
} else {
return redirect('login');
}
}
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function logout(Request $request)
{
Auth::logout();
return redirect('/login');
}
}
Routes
<?php
Route::get('/', function () {
return view('home');
});
Route::resource('project','ProjectController');
Route::resource('client','ClientController');
Route::resource('task','TaskController');
Route::resource('people','PeopleController');
Route::get('/login', function () {
return view('login');
});
Route::get('logout', '\App\Http\Controllers\Auth\LoginController#logout');
Auth::routes();
Route::get('/dashboard', 'DashboardController#index');
You should use a middleware for that. To get info on what a middleware is check here laravel.com/docs/master/middleware
Let's see how you can use the default Laravel's auth middleware for this purpose:
First of all get rid of your AdminBaseController and use only AdminController
Then you have to check that the auth middleware is enabled in the file app\Http\Kernel.php
You should have the line:
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
This means that the middleware is active and usable for your routes.
Now let's go inside the middleware class in app\Http\Middleware\Authenticate.php to specify the middleware's behaviour :
this method will be triggered before your controller constructor
public function handle($request, Closure $next)
{
//check here if the user is authenticated
if ( ! $this->auth->user() )
{
// here you should redirect to login
}
return $next($request);
}
Now the only thing left to do is to decide for what routes you should apply the middleware. Let's suppose you have two routes that you want to be only accessible from authenticated users, you should specify to use the middleware for these two routes in this way:
Route::group( ['middleware' => 'auth' ], function()
{
Route::get('admin/home', 'AdminController#index');
});
You should move your Auth::routes() before your first route
<?php
Auth::routes()
Route::get('/', function () {
return view('home');
});
And use auth middleware in your controllers where you want only authenticated user.
public function __construct()
{
$this->middleware('auth');
}
Move your Auth:Routes(); right after
Route::get('/', function () {
return view('home');
});
Then all your routes will be auth protected.

Can not access the user register or login page while login as admin

I am using laravel auth and trying to access the user login and register page while I am login as admin. But i can not access, I think there must be some changes in guards and providers. please help
I have only one table where I have defined the admin separately. fig is given.
Above the pictures from user table where for admin I assign 1 and for all others users assign zero. I can login on both and redirected on seperate views for user and admin. but on same time I can not access both user and admin.
HomeController.php code is given.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth;
use DB;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return view('home');
}
public function allusers()
{
$key['key'] = DB::table('users')->get();
return view('allusers',$key);
}
}
Code of routes is given here.
Auth::routes();
Route::group(['middleware' => ['web','auth']],function(){
Route::get('/', function () {
return view('welcome');
});
Route::get('/home', function(){
if (Auth::user()->admin==0) {
return view('home');
}
else {
$users['users'] = \App\User::all();
return view('adminhome', $users);
}
});
});
Please help what kind of changes I can do in guards and providers so I can access both on same time.
In your app/Http/Controllers/Auth/RegisterController.php you have a __construct() that checks if the user is guest then continue and you should change it
public function __construct()
{
$this->middleware('guest');
}
and you should change it like bellow to check that user is login
public function __construct()
{
$this->middleware('auth');
}
Note: By this change just logged in user will access to the registration page you should customize the condition as you want.
have a view on this link for log as admin
https://stackoverflow.com/a/42473137/9246297

how to completely logout in laravel 5.5 controller?

After I logout of my laravel application, in the browser I press the button to backward (go back) and then I see the dashboard.
I want to eliminate this "session" that laravel mantein if I go back.
can anyone help me?
EDIT: I have two login files, one is inside the Controllers/Auth and another is inside the Controller/. I'm sure this is not a good practice, but it's keeping my system up and running. how to solve this?
Controllers/Auth/LoginController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Session;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/';
/**
* Create a new controller instance.
*
* #return void
*/
private $user;
}
my Login Controllers/LoginController.php ->
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Session;
class LoginController extends Controller
{
private $user;
public function logout(){
Auth::logout();
\Session::flash('success',"logout");
return redirect()->route('login');
}
}
my DashboardController ->
use App\Authorization;
use App\BackLog;
use App\Key;
use App\isKeyInUse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
class DashboardController extends Controller
{
public function index() {
return view('dashboard');
}
}
my web.php ->
<?php
Route::get('/', 'LoginController#login')->name('login');
Route::get('auth/logout', 'Auth\LoginController#logout')->name('logout');
Route::get('/dashboard', 'DashboardController#index')->name('dashboard')->middleware('auth');
Route::post('/dashboard/getKey', 'DashboardController#getKey')->name('dashboard.key')->middleware('auth');
This is happening because caching. to prevent that we can create a middleware that intercepts every request and set the cache to expire in0 time and thus it will force the page to reload when the user press the back button here's the steps to create the middleware :
first
create a middleware i will call it MyAuth:
php artisan make:middleware MyAuth
second
register the middleware in app/Http/kernel.php
protected $routeMiddleware = [
...,
'my_auth' => \App\Http\Middleware\MyAuth::class,
];
third
in the newly created middleware app/Http/Middleware/MyAuth.php
public function handle($request, Closure $next, $guard = null)
{
$response = $next($request);
return $response
->withHeaders([
'Cache-Control' => 'no-store, no-cache, must-revalidate',
'Pragma'=> 'no-cache',
'Expires' => '0'
]);
}
}
Then
you can add your middleware like so:
Route::group(['middleware' => 'my_auth'], function() {
// All your routes you want to be secure
});
This code has been derived from this video
You are missing Request in logout function
public function logout(Request $request){
Auth::logout();
\Session::flash('success',"logout");
return redirect()->route('login');
}
And write in your dashboard controller
public function __construct()
{
$this->middleware('auth');
}
Insert these lines to your Dashboard controller and then check:
public function __contruct()
{
$this->middleware('auth');
}
This will check user is logged in or not? If user is loggedout, then it send to specific login page as you defined in auth middleware.
Pressing the Back button of your browser will load the previously loaded document. It is just visible but will not work for sure. For this you just have to override back press event from javascript.
See link How to Detect Browser Back Button event - Cross Browser
In Laravel 7.x, you can logout from the controller by using the following command:
Auth::logout()

Laravel middleware redirect loop

I have a small dilema, i'm trying to make a login system that differentiates normal users from admin users using the laravel auth scaffolding.
The problem is it goes in a infinite redirect loop in the middleware.
After I press the login button it constantly redirects to a route and the question is, how can I solve this issue the "laravel way" or any other way for that matter.
Here are my controllers:
1. The basic home controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return view('home');
}
}
The main admin controller - entry controller:
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class Start extends Controller
{
public function index(){
return view('admin/index');
}
}
Login Controller(the default one from the auth scaffolding- modified by me, I removed the constructor):
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = '/home';
}
The Middleware(redirect if RedirectIfAuthenticated):
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
if(Auth::user()->type == 2){//if user type is 1 then it's an admin.
return redirect()->route('web-admin');
}else{
return redirect()->route('home');
}
}
return $next($request);
}
}
The route file(web routes)
Route::get('/', function () {
return view('index');
});
Auth::routes();
Route::middleware(['auth','guest'])->group(function() {
Route::get('home',['as'=>'home', 'uses'=>'HomeController#index']);
Route::get('web-admin',['as'=>'web-admin', 'uses'=>'Admin\Start#index']);
});
The guest/RedirectIfAuthenticated redirects any request to corresponding home route for authenticated users. The problem is that admin home route is behind this middleware as well, that's why it keeps redirecting to the same page.
You need to remove the guest middleware from the route group - it should only be applied to routes that should be available to unauthenticated users only.
For sure this is an infinite loop because you applied both guest and auth middle ware to your routes, so also authenticated users will be redirected and this is an infinite loop.
Keep the RedirectIfAuthenticated.php as its original code and redirect authenticated users inside your main controller based on their type:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index(Request $request)
{
// if type 1 is admin, why did you redirect type 2 to web-admin?!
if($request->user()->type == 2) { //if user type is 1 then it's an admin.
return redirect()->route('web-admin');
}
return view('home');
}
}
You may do same redirection in your admin controller for normal users to redirect them back in case they try to access admin page.
Additionally modify web.php routes as following:
Route::get('/', function () {
if(auth()->user()->type == 2) { //if user type is 1 then it's an admin.
return redirect()->route('web-admin');
} else {
return redirect()->route('home');
}
})->middleware('auth');
Auth::routes();
Route::middleware('auth')->group(function() {
Route::get('home',['as'=>'home', 'uses'=>'HomeController#index']);
Route::get('web-admin',['as'=>'web-admin', 'uses'=>'Admin\Start#index']);
});

Categories