In a middleware, how can I get current logged in user? - laravel-5

I am creating a middleware that checks if user is currently logged in and is super admin.
This is my middleware code.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class CheckAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->guest()) {
// also need to check a field of user
return redirect()->guest('login');
} else {
return $next($request);
}
}
}
Actually, it's the same as the default middleware Authenticate (i.e. 'auth')
It's working well when I use it in app's routing. (app/Http/routes.php)
I need to use it with cuddy plugin middleware option. It should redirects only guest users, but it's not. Please help!

Authenticate middleware by default checks if user is guest and redirects him to login page see below
if (Auth::guard($guard)->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401); //if ajax request
} else {
return redirect()->guest('login'); //redirect
}
}
Now if u want to check if user is logged and check some user fields here how it should be
public function handle($request, Closure $next, $guard = null)
{
if(Auth::check()) { //If is logged in
$user = Auth::user();
if($user->isSuperAdmin())
return $next($request);
}
return redirect('/whatever');
}
If you attach 'auth' middleware + this custom middleware. You can get rid of "Auth::check()" in the custom middleware.
Route::group(['middleware' => ['web', 'auth', 'custom']], function () {
Route::get('/url/only/for/super/users', 'Whatever#whateverController');
});
public function handle($request, Closure $next, $guard = null)
{
$user = Auth::user();
if($user->isSuperAdmin())
return $next($request);
return redirect('/whatever');
}

There is many helper functions in laravel that you can use anywhere like auth() helper, see helpers. So you can use this code anywhere:
auth()->user();

Related

Prevent login to user and custom guards at the same time

I am using a custom guard for a different type of user using a custom guard labelled business_user.
I have noticed I am able to login to as both normal users (web) and my business_users.
I've read in the Pusher documentation that I used to create my custom guards in the first place to add additional middleware into my "LoginController".
But I don't actually even have a LoginController, I've created my own controllers for each user type. AuthController (for web) and BusinessController (for business_user).
I have created a third controller labelled LoginController with the following code:
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = '/dashboard';
public function __construct()
{
$this->middleware('guest')->except('logout');
$this->middleware('guest:business_user')->except('logout');
}
}
I also updated my RedirectIfAuthenticated as follows:
class RedirectIfAuthenticated
{
public function handle($request, Closure $next, $guard = null)
{
if ($guard == "business_user" && Auth::guard($guard)->check()) {
return redirect('/dashboard');
}
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
I also have a RedirectIfAuthenticated middleware inside my Middleware folder.
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if ($guard == "business_user" && Auth::guard($guard)->check()) {
return redirect('/dashboard');
}
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
}
When I land on my user login page, it still allows me to attempt logging in. Can someone tell me how to resolve this?
In LoginController, you can override authenticated method.
/**
* The user has been authenticated.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function authenticated(Request $request, $user)
{
auth()->login($user); // this method will login with default guard
return redirect()->intended($this->redirectPath());
}
I think because the order of middleware
<?php
public function __construct()
{
$this->middleware('guest')->except('logout'); // this procress first and redirect to login page
$this->middleware('guest:business_user')->except('logout');
}
So, I think you can check directly in __construct() of LoginController or in login view (blade file)
#if (Auth::check('business_user'))
You are already logged in (or perform a redirect somewhere)
#else
//display login form
#endif

Restrict page if Auth::user()->id != user_id using middleware

i use middleware to restrict the admin page from non-admins, and i can restrict pages with a list of "patients" from other users by using a policy, but if i use a policy. I have to repeat the code can() method in every function. If i use middleware to check if the user_id in the url == Auth::user()->id. I do not need to repeat this, but how do i get the user_id from the url in my middleware?
the route
Route::get('/patients/{patient}', 'PatientController#edit')
What i have now
PatientPolicy
public function view(User $user, Patient $patient)
{
// does this patient belong to user
return $user->id == $patient->user_id;
}
PatientController
public function edit(Patient $patient)
{
// authenticate logged in user
$user = auth()->user();
// can the loged in user do this?(policy)
if($user->can('update', $patient)){
return view('patient.edit-patient', compact('patient', 'user'));
}
return view('403');
}
what i should have in a middleware
UserMiddleware
/**
* #param $request
* #param Closure $next
* #return mixed
*/
public static function handle($request, Closure $next)
{
if (Auth::check() && Auth::user()->id == User::patients()->user_id) {
return $next($request);
} else {
return redirect()->route('login');
}
}
Does somebody know how to check if the {patient} in the routes user_id == the logged in user()->id?
Since you have Illuminate\Http\Request object injected into handle function in middleware this is pretty straight forward to get patient id from url:
/**
* #param $request
* #param Closure $next
* #return mixed
*/
public static function handle($request, Closure $next)
{
$patientId = $request->patient; // patient id from url!
$patient = Patient::find($patientId);
if (!$patient) {
return redirect()->back()->with(['message' => 'Patient not found!']);
}
if (Auth::check() && (int) Auth::user()->id === (int) $patient->id) {
return $next($request);
} else {
return redirect()->route('login');
}
}
Thank you #Leorent,
Your answer helped me alot and this is how it got fixed
Route
Route::get('/patients/{patient}', 'PatientController#show')->middleware('user');
UserMiddeware
public static function handle($request, Closure $next)
{
$patientId = $request->patient->user_id; // user_id from patient in url!
if (Auth::check() && (int) Auth::user()->id == $patientId) {
return $next($request);
} else {
return redirect()->route('403');
}
}
Thanks again!

Can't access user object

I am trying to handle roles in my application but I have a problem: when I clear cache or logout from the app and log in again I want to be redirected to the login but it sends me the following error
Trying to get property 'rol' of non-object.
<?php
namespace App\Http\Middleware;
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::user()->rol == 'Admin') {
return $next($request);
}
return redirect()->guest('login');
}
}
you have to check if user is logged in, and then ask if user have rol
use Illuminate\Support\Facades\Auth;
public function handle($request, Closure $next)
{
if (Auth::check()) {
if (Auth::user()->rol == 'Admin') {
return $next($request);
}
return redirect()->guest('login');
}
return redirect()->guest('login');
}

Auth After Middleware

I wish to authenticate the user after the request with my own middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Auth\Middleware\Authenticate;
class AuthenticateAfter extends Authenticate
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string[] ...$guards
* #return mixed
*
* #throws \Illuminate\Auth\AuthenticationException
*/
public function handle($request, Closure $next, ...$guards)
{
$response = $next($request);
$this->authenticate($request, $guards);
return $response;
}
}
I extend Illuminate\Auth\Middleware\Authenticate and modify the handle method to run as after middleware.
It's then declared in my kernel and on the correct route.
But I always get kicked back to the page I was previously on after logging in.
I want to control the page I go to, so before the middleware kicks in I do:
$request->session()->put('url.intended', 'my-test-url');
But it fails to redirect to this route.
How can I get it to redirect to a custom route?
Try this,
public function handle($request, Closure $next, ...$guards)
{
$response = $next($request);
$this->authenticate($request, $guards);
return redirect('/your_page_path');
}
Just for reference, here what I use to authenticate a user:
public function handle($request, Closure $next)
{
if (auth()->user() && auth()->user()->type != 'admin')
{
return redirect('/unauthorized');
}
return $next($request);
}
Try with: return redirect('view') or return redirect()->to('/route')

laravel 5 redirect user after login based on user's role

My 'users' table has a 'role' column and when users are registered or logged in, I want them to be redirected based on their role column. how can I do that?
I added this function to AuthController.php and everything fixed magically
public function authenticated($request , $user){
if($user->role=='super_admin'){
return redirect()->route('admin.dashboard') ;
}elseif($user->role=='brand_manager'){
return redirect()->route('brands.dashboard') ;
}
}
If you are using the Authentication system provided with Laravel you can override the redirectPath method in your Auth\AuthController.
For example, this would redirect a user with role 'admin' to /admin and any other user to /account:
public function redirectPath()
{
if (\Auth::user()->role == 'admin') {
return "/admin";
// or return route('routename');
}
return "/account";
// or return route('routename');
}
You could also use Laravel Authorization (introduced in 5.1.11) to manage role logic.
In laravel 5.7 there is no AuthController.php so you have to go Controllers\Auth\LoginController.php and add the below function,
If the redirect path needs custom generation logic you may define a redirectTo method instead of a redirectTo property
protected function redirectTo()
{
if($user->role=='super_admin'){
return '/path1';
}elseif($user->role=='brand_manager'){
return '/path2';
}
}
You can do this handle the request in the Middleware RedirectIfAuthenticated.php inside the handle function like this:
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
if (Auth::user()->role == 'admin') {
return redirect('/admin');
}else{
return redirect('/');
}
}
return $next($request);
}
I write this in case someone consider useful. If you want to redirect always and not only on Login, I did it on web.php like this:
Route::get('/home', function () {
switch(\Illuminate\Support\Facades\Auth::user()->role){
case 'admin':
return redirect(route('home.admin'));
break;
case 'employee':
return redirect(route('home.employee'));
break;
default:
return '/login';
break;
}
});
Route::get('/home/admin', 'HomeController#indexAdmin')->name('home.admin');
Route::get('/home/employee', 'HomeController#indexEmployee')->name('home.employee');
So every time they click on /home is redirect to the url you want, you could do it too with '/'.
for laravel 9 i implement the following code
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Auth;
use Spatie\Permission\Traits\HasRoles;
class LoginController extends Controller
{
use AuthenticatesUsers, HasRoles;
public function redirectTo(){
if(Auth::user()->hasAnyRole('Adm1','Adm2')){
return $this->redirectTo = route('viewAdm') ;
}elseif(Auth::user()->hasAnyRole('Usuario')){
return $this->redirectTo = route('home') ;
}
}
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}

Resources