Laravel Global Middleware Detected but Not Altering Model Records - laravel

I have the following middleware (LastSeen):
<?php
namespace App\Http\Middleware;
use Closure;
use Carbon\Carbon;
use Illuminate\Contracts\Auth\Factory as Auth;
class LastSeen
{
/**
* The authentication factory instance.
*
* #var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* Create a new middleware instance.
*
* #param \Illuminate\Contracts\Auth\Factory $auth
* #return void
*/
public function __construct(Auth $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->check()) {
$user = $this->auth->user();
$user->last_activity = Carbon::now();
$user->save();
}
return $next($request);
}
}
This was mostly taken from this answer ( Check if user online laravel ) as a stop-gap solution to a project I am working on.
I do have a TIMESTAMP column in my users table labeled last_activity and this is my Kernel file global middleware:
/**
* 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,
\App\Http\Middleware\LastSeen::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\ModifyHeadersMiddleware::class,
];
I'm not sure where to go next, I am just beginning on middleware and am still learning but not sure what I'm doing wrong...
Thanks!

The problem is that info about authorized user is stored in session and LastSeen's auth check is running before session was started so it allways return false.
You need to move LastSeen middleware after StartSession middleware:
/**
* 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,
\App\Http\Middleware\LastSeen::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];

There are some issues, but the main mistake is you are calling the wrong Auth. You have to call the facade, you are calling the Auth factory. Another thing is, avoid the constructor. Keep it simple. Especially for MiddleWare. One last thing, you are updating the user status, not saving a new entry.
namespace App\Http\Middleware;
use Closure;
use Carbon\Carbon;
use Auth;
class LastSeen
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::check()) {
$user = Auth::user();
$user->last_activity = Carbon::now();
$user->update();
}
return $next($request);
}
}

Related

Laravel VerifyCsrfToken exclude not working

I'm having an issue excluding /api route from verifying token.
I'm trying to exclude all routes but not working
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
//
'*',
];
}
What I suggest is, create a middleware and use it in your routes:
Create app/Http/Middleware/Cors.php
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
class Cors
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, \Closure $next)
{
$response = $next($request);
$response->headers->set('Access-Control-Allow-Origin', '*');
$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE');
$response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization');
return $response;
}
}
Modify app/Http/Kernel.php
protected $routeMiddleware = [
...
'cors' => \App\Http\Middleware\Cors::class,
];
Finally, use it in your route file eg: routes/web.php
Route::middleware(['cors'])->group(function () {
Route::get('/', 'YourController#yourFunction');
});

Laravel not changing language

Laravel is not changing the language I have tried these methods in controller
if ($request->lang === 'English') {
config(['app.locale' => 'en']);
} else {
config(['app.locale' => 'ar']);
}
and this method
App::setLocale('ar')
Or this method
\App::setLocale('ar')
What should I do?
You can create a middleware that puts the locale in the session and sets it.
php artisan make:middleware SetLocale
app\Http\Middleware\SetLocale.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
class SetLocale
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
if ($request->input('lang') == 'English') {
$request->session()->put('locale', 'en');
} else {
$request->session()->put('locale', 'ar');
}
App::setLocale($request->session()->get('locale'));
return $next($request);
}
}
Then, add it to your global middleware (or to a middleware group).
app\Http\Kernel.php
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
// other global middlewares
\App\Http\Middleware\SetLocale::class,
];

Check Auth::user() from middleware

I try to check in middleware if user is authenticated by calling Auth::user()
But it returns null. I call this middleware last in list of protected $middleware section in Kernel.php. Is there an way to check from middleware if user is authenticated or how I should do it another way?
Addition: I'm using Zizaco Entrust. May be it is why it doesn't work
And I'm using Laravel 5.5
my app/HTTP/Kernel.php:
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,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\FirstLoginPasswordChange::class,
];
my FirstLoginPasswordChange middleware:
use Illuminate\Support\Facades\Auth;
use Zizaco\Entrust\Entrust;
public function handle($request, Closure $next)
{
dd(Auth::user()); // returns null
// or
dd(Auth::check()); // returns false
// or
dd(\Entrust::user()); // returns null
return $next($request);
}
}
problem solved by moving middleware from protected $middleware section in Kernel.php to protected $routeMiddleware section in Kernel.php
using this article:
http://laraveldaily.com/password-expired-force-change-password-every-30-days/
To check if user is authenticated you can do as Laravel Docs states:
use Illuminate\Support\Facades\Auth; //be sure to add the facade
if (Auth::check()) {
// The user is logged in...
}
If you are trying to get user details and do some logic, then you can do this in your middleware:
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$role = Auth::user()->role; //Obtenemos el rol del usuario
if ($role != "user"){
return redirect('/logout');
}
return $next($request);
}
}

In My Laravel Passport Application, how can I accept access_tokens (when the client does not send a Bearer header)

I am using an OAuth2 client that does not send Authorization: Bearer but the standard laravel/passport setup checks this header. How to make it compatible from Laravel side?
Add the following middle ware
<?php
namespace App\Http\Middleware;
class ConvertTokenToBearer
{
/**
* #param \Illuminate\Http\Request $request
* #param $next
*
* #return \Symfony\Component\HttpFoundation\Response
*/
public function handle($request, $next)
{
if ($request->get('access_token')) {
$request->headers->set('Authorization', 'Bearer ' . $request->get('access_token'));
}
$response = $next($request);
return $response;
}
}
And add it to your app/Http/Kernel.php file.
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 = [
\App\Http\Middleware\ConvertTokenToBearer::class,
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];

Laravel 5 Middleware Doesn't work

I have problem with my custom middleware. It doesn't work. I have registered it in Kernel.php, only in $routeMiddleware. Here is my code:
/**
* The application's route middleware.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'test' => \App\Http\Middleware\TestMiddleware::class
];
}
Here is my Controller Code:
/**
* Middleware Activated
*/
public function __constructor()
{
$this->middleware('test');
}
and here is my custom middleware code:
protected $auth;
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (!$this->auth->check())
{
return redirect('/');
}
return $next($request);
}
When I'm logout and type in url
profile/21
it shows me the profile of user with id 21. I want to prevent that with middleware but it won't work for me.
Does anyone have an idea how to do that or where is the mistake?
To make sure if the middleware gets triggered put something like die('middleware triggerd'); inside the handle function of the middleware.
I noticed you have function __constructor() instead of function __construct().
That might be the problem.
If it does trigger the middleware but you still have the same problem try replacing:
if (!$this->auth->check()) with if (!\Auth::check())

Resources