Laravel 5.3 middleware execution order bug - laravel

I'm having a problem:
No matter what I do, the auth middleware is ALWAYS executed before other middlewares!
Here's what I tried:
Created a middleware named aa (so it comes before auth at least alphabetically).
I also put it before the auth one in Kernel.php
Then I created a nested route group:
Route::group(['prefix' => 'test', 'middleware' => 'aa'], function() {
Route::get('/', function() {
return 'test';
});
Route::group(['prefix' => 'test2', 'middleware' => 'auth:api'], function() {
Route::get('/', function() {
return 'test2';
});
});
});
If I go to /test/test2 the auth middleware gets executed before the aa one.
If I go to /test then I see the aa middleware is executed..
the middleware code is really easy:
public function handle($request, Closure $next)
{
dd('aa middleware!');
}
Here is Kernel.php as requested from #Rimon Khan
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
];
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'bindings',
],
];
protected $routeMiddleware = [
'aa' => \App\Http\Middleware\Aa::class,
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class
];
}
Edit: #prateekkathal you will never convert me to use spaces instead of tabs even if you force edit my post and change the indentation! lol

I got the answer. You should override the $middlewarePriority in your Kernel.php.
/**
* The priority-sorted list of middleware.
*
* Forces the listed middleware to always be in the given order.
*
* #var array
*/
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Auth\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];

Related

How to fix ERR_TOO_MANY_REDIRECTS using Laravel Middleware?

I am using Laravel 8 and when i redirect a route from middleware i am facing issue
ERR_TOO_MANY_REDIRECTS. I am verifying user with firebase otp and set cookie if otp verify then i want to redirect register page if user not exist in db. I have create middleware and check if cookie set then redirect to register route.
public function handle(Request $request, Closure $next)
{
if (Cookie::get('otpVerified')){
return redirect()->route('register');
}
return $next($request);
}
after that i am facing this issue
enter image description here
my route file is
Route::get('/register', [RegisterController::class, 'register'])->name('register_user');
Auth::routes();
Route::group(['middleware' => 'otpVerify'], function (){
Route::get('/404', [\App\Http\Controllers\ErrorController::class, 'notFound'])->name('404');
Route::get('/', [\App\Http\Controllers\Dashboard\DashboardController::class, 'index'])->name('dashboard');
});
How can i fix it. My kernel file is
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
and
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'otpVerify' => \App\Http\Middleware\OTPVarification::class,
];
In this section, you must exclude the register root
public function handle(Request $request, Closure $next)
{
if (Cookie::get('otpVerified') && $request->route()->getActionName() !== 'YourRegisterAction'){
return redirect()->route('register');
}
return $next($request);
}

Laravel middleware Auth work in controller but not in my middleware

i'm in trouble for 2 days with the laravel auth middlewares.
I have understand how the Auth system work with JWTtoken. In my controller all work fine i got my user login and i can access with Auth::guard->user().
But i have one problem in my middleware Authenticate.php :
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Support\Facades\Auth;
use Closure;
class Authenticate extends Middleware
{
protected function redirectTo($request)
{ dd(
$request->user(),
auth()->id() ?? '?',
Auth::id() ?? '?',
$request->user()->id ?? '?',
auth()->check(),
get_class(auth()->guard())
);
}
}
I try everything i found in multiple post or tutorial, but the result is the same (same time in controller all work user is login) :
null
"?"
"?"
"?"
false
"Tymon\JWTAuth\JWTGuard"
AuthController.php
public function __construct()
{
$this->middleware('auth', ['except' => ['login', 'register']]);
}
public function login(Request $request){
$credentials = $request->only('email', 'password');
if(!$token = $this->guard()->attempt($credentials)){
return response()->json(['error' => "L'email ou le mot de passe ne correspondent pas."]);
}else {
return response()->json([
'token' => $token,
]);
}
}
public function guard()
{
return Auth::guard();
}
And Multiple function me,logout...
Kernel.php
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
//'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
}
I have try to take rules in $middlewareGroups web and past in $middleware, and if i do that is say :
"Call to a member function parameters() on null".
So nothing change my Auth is null.
Thanks a lot if someone can explain me the problem and what i do wrong !
EDIT :
api.php
Route::group(['prefix' => 'auth', 'namespace' => 'Auth'], function ($router) {
Route::post('/inscription', 'AuthController#register');
Route::post('/connexion', 'AuthController#login');
Route::get('/logout', 'AuthController#logout');
Route::get('/me', 'AuthController#me');
Route::get('/isAdmin', 'AuthController#isAdmin');
});
Solution not found :(
Authenticate.php
public function handle($request, Closure $next, ...$guards)
{
$this->authenticate($request, $guards);
$user = $this->auth->user();
...do your thing....
Kernel.php
protected $middlewareGroups = [
'api' => [
\Illuminate\Session\Middleware\StartSession::class,
\AEPlanning\Http\Middleware\VerifyCsrfToken::class,
You will get user only after successful login

Permission Middleware with Laravel 6.6 working on all routes

Hi I am working on laravel project , I have to check about user's permission when he trying to access one page , my problem is after I created Permission middle ware , and add it in the kernel.php , it checking about permissions for all route even I did not call it in any route .
I don't want to apply this middleware on all route , just some of it .
this is my permission middleware's code
namespace App\Http\Middleware;
use Closure;
use Session;
use App\Rules;
use Illuminate\Support\Facades\Route;
use URL;
class Permissions
{
public function handle($request, Closure $next) {
$rolename=Session::get('rule_name') ;
$route = $request->path();
$hasPermission = Rules::where('rule_name', 'superadmin')->where('allowed_pages', 'like', '%' . $route . '%') ->first();
if (empty($hasPermission)) {
echo 'Unauthorized.Go Back';
die();
}
}
}
}
and this is my route file
Route::resource('Login', 'LoginController')->name('index','Login');
Route::resource('Backup', 'BackupController')->name('index','Backup');
as you see I did not apply the middleware on these tow route , but the middleware is working with these tow routes
this is my kernel code
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
'Permissions' => \App\Http\Middleware\Permissions::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
I want to run this middleware only by route like this
Route::group(['middleware' => 'permissions'], function () {
Route::resource('Backup', 'BackupController')->name('index','Backup');
}
thank you for advance
best regards
You added your middleware to the middelwareGroup web, wich applies the middleware to every request comming in.
You need to add your middleware to the routes middleware array: docs
// Within App\Http\Kernel Class...
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
...
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
// your own middlewares:
'Permissions' => \App\Http\Middleware\Permissions::class,
];
You can than apply the middleware to specific routes:
Route::resource('Login', 'LoginController')->middleware('Permissions')->name('index','Login');
you added inside web which is default middleware by laravel that's why it's applied in all route.
to register a middleware you need to add in protected $routeMiddleware = [ ] array
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
//custom middlewares:
'Permissions' => \App\Http\Middleware\Permissions::class,
];
then only
Route::group(['middleware' => 'permissions'], function () {
Route::resource('Backup', 'BackupController')->name('index','Backup');
}
it will work

Auth::check() is always false in middleware in Laravel 5.7

I have used middlewares for many Laravel applications, but this is a stupid situation never happened to me before. The middleware always returns false for Auth::check()
This is routes of User module
<?php
Route::group(['middleware' => 'web', 'namespace' => 'Modules\User\Http\Controllers'], function () {
Route::get('/', 'UserController#index');
Route::get('login', 'LoginController#showLoginForm')->name('login');
Route::post('login', 'LoginController#login');
Route::post('logout', 'LoginController#logout')->name('logout');
});
Route::group(['middleware' => 'admin', 'prefix' => 'user', 'namespace' => 'Modules\User\Http\Controllers'], function () {
Route::get('register', 'RegisterController#showRegistrationForm')->name('register');
Route::post('register', 'RegisterController#register');
});
This is AdminMiddleware inside the User module
<?php
namespace Modules\User\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AdminMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
$log = Auth::check();
dd($log);
return $next($request);
}
}
and this is kernel.php
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'admin' => \Modules\User\Http\Middleware\AdminMiddleware::class
];
But the result of dd($log) is always false. What is wrong here?!!!
You also need to add web middleware to User module routes group.
Because the session starts there.
Just saying, another solution is that you added it to the global middleware stack instead of the web middleware group! (Only add it to web, it can't be both)
please append your middleware address:
\Modules\User\Http\Middleware\AdminMiddleware::class
to
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Modules\User\Http\Middleware\AdminMiddleware::class //this is your middleware.
],
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
you can set your middleware's priority to be loaded after StartSession to be sure it will be loaded after the session starts.
in kernel.php
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Modules\User\Http\Middleware\AdminMiddleware::class
\App\Http\Middleware\Authenticate::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
\App\Http\Middleware\CheckProfileRequiredData::class, // putting CheckProfileRequiredData after Auth priority is required! to perform it's check after auth middleware
\App\Http\Middleware\CheckUserMustPayWithoutAnsweringDietRequiredQuestions::class,
];

"Unauthenticated" error on a route that is not protected

Part of my application does not utilize standard user authentication, and lies outside the auth group in my routes file. I am using Laravel Passport, VueJS2, VueRouter. Laravel is serving two blade files; one for the authenticated part of the application, and the other for the non-authenticated part.
However, I find that when trying to access that part of the application, it still requires me to be authenticated (I get the 401: Unauthorized error).
I have looked through my configuration files, and I can't seem to figure out why this would be displayed.
My api.php file:
<?php
use Illuminate\Http\Request;
Route::group(['middleware' => 'auth'], function () {
// A lot of routes here...
});
// These should not be guarded
// This is the route that triggers the unauthenticated message
Route::post('authenticate', 'TestController#authenticate');
THe JS file that makes the request:
authenticateUser: function() {
var data = {
'id' : this.$route.params.id,
'passcode' : this.state.password,
};
var that = this;
axios({
method: 'post',
url: '/api/authenticate',
withCredentials: true,
data: data,
}).then(function(response) {
swal('Great!', 'You have been authenticated.', 'success');
that.$router.push('/client/create/' + that.$route.params.id);
}, function(error) {
swal('Woah!', 'Wrong password, go away.', 'error');
});
}
Here is my kernel.php file:
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* #var array
*/
protected $routeMiddleware = [
'test.auth' => \App\Http\Middleware\VerifyTestAccess::class,
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'test.state' => \App\Http\Middleware\VerifyTestState::class,
];
}

Resources