Laravel Redirect If Authenticated middleware - php

I have three type of users for the application, Each one have its own dashboard. I need a check that adminor any other user cannot see another user dashboard.
There is a middleware RedirectIfAuthenticated :
public function handle($request, Closure $next, $guard = null){
if (Auth::guard($guard)->check() && auth()->user()->type == 'admin'){
return redirect('/admin');
}
if (Auth::guard($guard)->check() && auth()->user()->type == 'author'){
return redirect('/author');
}
if (Auth::guard($guard)->check() && auth()->user()->type == 'client'){
return redirect('/client');
}
}
Its under guest middleware.
The above code seems good to me but when i tests it, The browser says Too many redirects.
What am i doing wrong, What will be the best way to handle it.

You may have misunderstood the purpose of that middleware. The purpose of RedirectIfAuthenticated is to redirect a user to their default authenticated page. It is not meant to block unauthenticated/unauthorised users from accessing specific areas.
What you need to do is redirect if not authorised. Since this is a simple case you can just have a middleware:
class RequireRole {
public function handle($request, Closure $next, $role) {
abort_unless(auth()->check() && auth()->user()->type == $role, 403, "You don't have permissions to access this area");
return $next($request);
}
}
Then register this middleware in your Kernel.php
protected $routeMiddleware = [
//Other middleware
"requirerole" => RequireRole::class
];
Then you can use it in your routes e.g.
Route::get('/admin', function () { /* action */ })->middleware("requirerole:admin");
However if you find yourself in need of more complex rules then take a look at Authorization

Need to modify the code a bit
public function handle($request, Closure $next, $guard = null){
if (Auth::guard($guard)->check() && auth()->user()->type == 'admin'){
return redirect('/admin');
}
if (Auth::guard($guard)->check() && auth()->user()->type == 'author'){
return redirect('/author');
}
if (Auth::guard($guard)->check() && auth()->user()->type == 'client'){
return redirect('/client');
}
return $next($request);
}

You have to add an extra check for every if statement to see if you are not already on the route where it's going to redirect to
Maybe something like:
&& $request->is('admin')

Just split your checks and keep the original return:
public function handle($request, Closure $next, $guard = null){
if (Auth::guard($guard)->check()){
if(Auth::user()->type == 'admin'){
return redirect('/admin');
}
if(Auth::user()->type == 'author'){
return redirect('/author');
}
if(Auth::user()->type == 'client'){
return redirect('/client');
}
}
return $next($request);
}

As pointed in the accepted answer, the purpose of the middleware is to redirect a user if he is authenticated.
Now if you check App\Http\Kernel.php you will see that the middleware is attached to guest route middleware variable.
So any route you assign the middleware of guest will not be accessible to an authenticated user.
To solve your problem create another middle as pointed in the accepted answer.
What you need to do is redirect if not authorised. Since this is a simple case you can
just have a middleware:
public function handle($request, Closure $next, $role) {
abort_unless(auth()->check() && auth()->user()->type == $role, 403, "You don't > have permissions to access this area");
return $next($request);
}
}
Then register this middleware in your Kernel.php
//Other middleware
"requirerole" => RequireRole::class
];
Then you can use it in your routes e.g.
Route::get('/admin', function () { /* action */ })->middleware("requirerole:admin");
In reality, you may not need to modify default files that come with laravel unless it is inevitable.

Related

Passing data from controller to middleware laravel

I have a problem when I want to pass data to the view via the middleware to count the number of users. when not using middleware, variable from controller get to the view.
my HomeController.php
public function index()
{
$count = User::count();
return view('admin.Dashboard', compact($count);
}
my Middleware
public function handle(Request $request, Closure $next)
{
if ($request->user() && $request->user()->role == 'admin') {
return response()->view('admin.Dashboard');
} else {
return response()->view('member.dashboard');
}
return $next($request);
}
the $count variable if using middleware in route not passed to the view
my web.php
Auth::routes(['verify' => true]);
Route::get('/dashboard', 'HomeController#index')->middleware('verified', 'cekrole')->name('home');
In your middleware you are returning response (a view), so
return $next($request);
will never be executed, so neither will your controller.
User call /dashboard > Your middleware is called > if it's an admin you are returning admin.Dashboard, else member.dashboard.
But you never execute code in your Controller.
As a quick fix you could replace your Middleware by :
public function handle(Request $request, Closure $next)
{
if ($request->user() && $request->user()->role == 'admin') {
$count = User::count();
return view('admin.Dashboard', compact('count'));
}
return response()->view('member.dashboard');
}
or make those test (admin/not admin) in your controller

Laravel 6 Error: Page not redirecting to the defined route

I've been stuck here for a while. I hope I can clearly explain the issue. I'm trying to have separate pages for admin and user. For that, I have created an admin middleware. Now when I login, it redirects me to the same page either its admin or user. I want it to go to admin dashboard when admin logs in and to the user home when user logs in. I hope the issue is clear.
Here is the AdminMiddleware code:
public function handle($request, Closure $next)
{
if(Auth::user()->user_type == 'admin') //If usertype is admin
{
return $next($request);
}
else {
return redirect('home');
}
}
Here are the routes code:
Route::get('/','HomeController#index');
//For Admin
Route::group(['middleware' => ['auth','admin']], function() {
Route::get('/admin','HomeController#home_page');
Route::get('/users-list', 'UserController#users_list');
});
Here is the HomeController code:
public function index()
{
return view('home', compact('currantWorkspace'));
}
I've added the Middleware path to kernel.php file.
I'll be happy to provide any other details if needed. Any solutions/suggestions will be highly appreciated.
Edit
I've tried this, but still issue.
protected function redirectTo(){
if (Auth::user()->user_type != 'admin') {
return 'admin';
//return redirect('/admin');
}
else {
return 'home';
//return redirect('/');
}
}
I think the redirectTo function is not working, or not checking the if/else conditions
Why don't you create an 'if, else' statement in your login function like:
if(Auth::user()->user_type == "Admin"){
return Redirect::route('dashboard');
}else if(Auth::user()->user_type == "Standard User"){
return Redirect::route('home');
}
Change the route as follows.
Route::get('/','HomeController#index')->name('home');
Route::group(['middleware' => ['auth','admin']], function()
{
Route::get('/admin','HomeController#home_page')->name('admin.home');
Route::get('/users-list', 'UserController#users_list');
});
Change the redirect statement in middleware as
public function handle($request, Closure $next)
{
if(Auth::user()->user_type == 'admin') //If usertype is admin
{
return $next($request);
}
else
{
return redirect()->route('home');
OR
return redirect('/');
}
}
There are a few problems, currently, the key thing is that the middleware you defined is not being called when anyone tries to log in.
To make it work I think you just need to add this to your LoginController.php
protected function authenticated()
{
if (Auth::user()->user_type == 'admin') {
return redirect('dashboard');
}
return redirect('home');
}
This method basically tells laravel what you want to do after the user is logged in.

How to allow guest access to page while still using "middleware:('verified')" on Laravel 5.8?

I want the guest to access Home and Shop page and still verifies email when a user wants to register.
Route::get('/home', 'HomeController#index')->name('home')->middleware('verified');
The EnsureEmailIsVerified middleware requires the user to be logged in to access any pages protected with it.
You can see this check in the code for the middleware
if (!$request->user() ||
($request->user() instanceof MustVerifyEmail &&
!$request->user()->hasVerifiedEmail())) {
// reject
}
If you want to allow guests to access the page, and still require users to be activated you will need to create a custom middleware.
php artisan make:middleware GuestOrActivated
Then, for the handle function:
public function handle($request, Closure $next, $redirectToRoute = null)
{
if ($request->user() && $request->user() instanceof MustVerifyEmail && !$request->user()->hasVerifiedEmail()) {
return $request->expectsJson()
? abort(403, 'Your email address is not verified.')
: Redirect::route($redirectToRoute ?: 'verification.notice');
}
return $next($request);
}
For that case I make new middleware, before redirect to email verify, I flush the session, so when user back to home, he will redirect to login again
class GuestOrActivated
{
public function handle($request, Closure $next, $redirectToRoute = null)
{
if ($request->user() && $request->user() instanceof MustVerifyEmail && !$request->user()->hasVerifiedEmail()) {
request()->session()->flush();
return Redirect::route('verification.notice');
}
return $next($request);
}
}

Laravel auth redirection

I have trouble redirecting after user authentication. I would like to redirect admin to admin panel, and user to home so I made admin middleware:
public function handle($request, Closure $next)
{
if (Auth::user() && Auth::user()->isAdmin()) {
return $next($request);
}
return redirect('/');
}
Routes for admin panel are:
Route::prefix('admin')->middleware(['web', 'admin', 'auth'])->group(function () {
Route::get('/', 'HomeController#index');
Route::resource('user', 'Admin\UserController');
});
I have User and Role models in a M-2-M relationship.
User model:
public function role(){
return $this->belongsToMany('App\Role');
}
public function isAdmin()
{
return ($this->role->first()->name == 'Admin') ? true : false;
}
Auth LoginController:
protected $redirectTo = '/admin';
Auth RedirectIfAuthenticated:
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/');
}
return $next($request);
}
Issue I'm having is that I always end up on home page. When watching through the inspector I noticed something strange, don't know if it is a standard procedure or not:
Login seems to be triggered twice? Route to /admin was triggered and got 200 OK status, but I never got to see it. If I manually enter it to the browser however, it will lead me to the admin dashboard.

Additional auth middleware in Laravel 5.4

I want to add additional middleware to user model. User table has row 'approved' which is boolean (default is false). So when user logins - middleware should check if 'approved' is equal to true. If not, redirect to error page. What i got so far:
<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
class ConfirmedMiddleware
{
public function handle($request, Closure $next, $guard = null)
{
if(Auth::user()->approved != true){
redirect('/error');
}
return $next($request);
}
}
So far middleware attached here:
Route::get('/home', 'HomeController#index')->middleware('confirmed')->name('home');
However, it does not work. No errors as well.
You're better off checking this when a user logins instead of using a middleware.
Add this to the LoginController and perform any additional checks. This method will be called after the user successfully logs in.
protected function authenticated($request, $user)
{
if($user->approved != true){
return redirect('/error');
}
}
If you still insist on using middleware, then make sure you add the middleware in Kernel.php
Add this in app/Http/Kernel.php
'confirmed' => \App\Http\Middleware\ConfirmedMiddleware::class,
You're also missing the return in your redirect.
public function handle($request, Closure $next, $guard = null)
{
if(Auth::user()->approved != true){
return redirect('/error');
}
return $next($request);
}
You are missing the return in the redirect, It should be:
return redirect('/error');

Categories