Laravel - Redirect authenticated users - php

In my Laravel application I have a registration system that uses the default scaffolding created via php artisan make:auth to register new users, but after logging in I wanted to take the user to another page called member-type so that they can select what type of member they'd like to be.
I utilitized protected function authenticated(Request $request, $user) which comes from AuthenticatesUsers to check that a user has successfully logged in, I then check whether a member type is set.
The method looks like this:
/**
* The user has been authenticated.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function authenticated(Request $request, $user)
{
Log::info("{$user->log_reference} logged in to their account with IP: {$request->getClientIp()}");
if(!$user->investor_type_selected){
// dd('I NOT SELECTED');
return redirect()->route('user.investor-type');
} elseif(!$user->member_type_selected){
dd('M NOT SELECTED');
return redirect()->route('user.member-type');
} else{
dd('BOTH SELECTED');
return redirect()->route('user.dashboard');
}
}
The methods member_type_selected andinvestor_type_selectedcome from myUser` model and they look like this:
/**
* Check whether this user has selected an investor type
*/
public function getInvestorTypeSelectedAttribute()
{
return !empty($this->investor_type) ? true : false;
}
/**
* Check whether this user has selected an investor type
*/
public function getMemberTypeSelectedAttribute()
{
return !empty($this->member_type) ? true : false;
}
Pretty simple stuff.
The dump and die was there to test whether the statements were executing.
Anyway, the issue I have is with the Middleware RedirectIfAuthenticated which looks like this as I'm using a custom guard:
/**
* 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)
{
switch ($guard) {
case 'admin':
if (Auth::guard($guard)->check()) {
return redirect()->route('admin.dashboard');
}
break;
default:
if (Auth::guard($guard)->check()) {
return redirect()->route('user.dashboard');
}
break;
}
return $next($request);
}
Now, as soon as a user is authenticated this kicks in and bypasses my redirects with authenticated. I need this Middleware generally to make sure users get back to their dashboard, but is there a way to prevent this bypassing my redirects?

no need to override authenticated function , try this in your RedirectIfAuthenticated middleware
public function handle($request, Closure $next, $guard = null)
{
switch ($guard) {
case 'admin':
if (Auth::guard($guard)->check()) {
return redirect()->route('admin.dashboard');
}
break;
default:
if (Auth::guard($guard)->check()) {
$user = Auth::guard($guard)->user();
if(!$user->investor_type_selected){
return redirect()->route('user.investor-type');
} elseif(!$user->member_type_selected){
return redirect()->route('user.member-type');
} else{
return redirect()->route('user.dashboard');
}
}
break;
}
return $next($request);
}

Related

Laravel 8 | Redirect according to role after login

i am using Laravel as Framework, I'm creating a page with various types of roles, I have the authentication controlled with a middleware, so far so good. My problem is with the redirection after login. I have my users table with a field called "Rol" I need, before entering the system, to verify that "Rol" has my user and according to that, I am redirected to a dashboard or another.
Route::get('/dashboard', [GeneralController::class,'redirectAfterLogin'])->middleware(['auth'])->name('dashboard');
i am using this in the routes. i have un general controller with a function called "redirectAfterLogin"
This is my function
public function redirectAfterLogin(Request $request){
$role = $request->user()->role;
switch ($role) {
case 'Admin':
return redirect(route('admin/dashboard'));
break;
case 'SubAdmin':
return redirect(route('cita/addAppointment'));
break;
case 'Medico':
return redirect(route('cita/pattientsToday'));
break;
case 'Paciente':
return redirect(route('cita/decideLevel'));
break;
default:
# code...
break;
}
}
This works for me, but I don't think it's the right way. I know that with a middleware you can control this, but I don't know how, or what else should change for that middleware to work
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure(\Illuminate\Http\Request):
(\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* #param string|null ...$guards
* #return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
if($request->user()->role == "Admin"){
return "/AdminDashboard";
}else{
return "/GeneralDashboard";
}
}
}
return $next($request);
}
}
This middleware is supposed to handle redirects but no matter how I do it it doesn't happen
Ok, I managed to find the solution. I implemented a predesigned login with Brezze (I think that's how it is written) The point is that to redirect it creates a controller called "AuthenticatedSessionController"
This has the "store" method where the verification of the session data is done and if they are correct it is redirected to "HOME"
This is where we put our logic, in my case I did it with a switch.
class AuthenticatedSessionController extends Controller
{
/**
* Handle an incoming authentication request.
*
* #param \App\Http\Requests\Auth\LoginRequest $request
* #return \Illuminate\Http\RedirectResponse
*/
public function store(LoginRequest $request)
{
$request->authenticate();
$request->session()->regenerate();
$role = $request->user()->role;
switch ($role) {
case 'Admin':
return redirect(route('admin/dashboard'));
break;
case 'SubAdmin':
return redirect(route('cita/addAppointment'));
break;
case 'Medico':
return redirect(route('cita/pattientsToday'));
break;
case 'Paciente':
return redirect(route('cita/decideLevel'));
break;
}
}
Now, there is also a middleware called "RedirectIfAuthenticated", it takes care of the redirects after you are logged in and change the url to the root.
Let me explain, suppose I have 2 users Admin and Public, each one has a different HOME, when logging in who redirects you to the correct HOME, it is the "AuthenticatedSessionController" controller, and if after logging in you write in the URL
"http://My_domain/" (i mean, the root) will be the middleware "RedirectIfAuthenticated" who makes the redirection to the correct HOME. The controller only works when you login, the other times the middleware will do it.
In my middleware i have this.
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure(\Illuminate\Http\Request):
(\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* #param string|null ...$guards
* #return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
$role = $request->user()->role;
switch ($role) {
case 'Admin':
return redirect(route('admin/dashboard'));
break;
case 'SubAdmin':
return redirect(route('cita/addAppointment'));
break;
case 'Medico':
return redirect(route('cita/pattientsToday'));
break;
case 'Paciente':
return redirect(route('cita/decideLevel'));
break;
}
}
}
return $next($request);
}
Both the controller and the middleware are created by Brezze, I don't know how it will work with other login templates. But at least in Brezze I think this would be the correct way to redirect.
Your problem is return string, you need add return redirect(url_name)
Try this code, I think she will help you.
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
switch (Auth::guard($guard)->user()->role){
// Redirect Admin Dashboard
case 'Admin':
return redirect('/AdminDashboard');
break;
// If need any Roles for example:
case: 'RoleName':
return redirect('url');
break;
default: return redirect('/GeneralDashboard');
}
}
}
return $next($request);
}

Laravel Middleware based on a relation

In my Laravel application, administrators can be assigned to jobs, I also have super administrators that can do everything.
Administrators that are not super administrators should only be able to access jobs they are assigned to.
Let's use a rough route for illustration:
http://localhost:3000/jobs/{job}
http://localhost:3000/jobs/{job}/notes{note}
In this scenario {job} is an id acquired via route model binding and a note is attached to a job.
Administrators assigned to jobs are done so via the following relationship method:
/**
* Get the jobs that this admin has access to via the pivot table
*
* #return void
*/
public function jobs()
{
return $this->belongsToMany(JobPost::class, 'job_post_admin', 'admin_id', 'job_post_id');
}
So I can use $user->jobs
I want to be able to say the following - if you're a super admin you can go anywhere, if you're not, you should be restricted to what you've been assigned to.
So if a user only has access to http://localhost:3000/jobs/{1} and they go to http://localhost:3000/jobs/{2} they should be redirected.
I created a Middleware called Access
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::guard('admin')->user()) {
$user = Auth::guard('admin')->user();
if ($user->is_admin) {
return $next($request);
} else {
if ($user->jobs->contains($job)) {
return $next($request);
} else {
return response('You do not have sufficient priveledges to perform this action.', 403);
}
}
} else {
return redirect()->back();
}
}
However, I'm confused as to how I would get the job ID from the URL.
I have a working MiddleWare that looks like this:
<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
class Access
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::guard('admin')->user()) {
$user = Auth::guard('admin')->user();
$job = $request->vacancy;
if ($user->is_admin) {
return $next($request);
} else {
if ($user->jobs->contains($job)) {
return $next($request);
} else {
return response('You do not have sufficient priveledges to perform this action.', 403);
}
}
} else {
return redirect()->back();
}
}
}
I am now interested though, as without sounding dense I haven't really acknowledged authorization in Laravel, does it have benefits over Middleware?
Authentication is different to authorization. Laravel supports both.
You can do what you need using authorisation policies, there is no need for extra middleware.
First create a policy:
php artisan make:policy JobsPolicy --model=Job
This will make your boilerplate. Then you can add the actions:
class JobsPolicy {
use HandlesAuthorization;
//If you return true here the policy always succeeds
public function before(User $user, $ability) {
if ($user->is_admin) {
return true;
}
}
public function view(User $user, Job $job) {
return $user->jobs->contains($job);
}
public function create(User $user) {
return true; //Return true if the user can create jobs
}
public function update(User $user, Job $job) {
return $user->jobs->contains($job);
}
}
You need to also register your policy in the AuthServiceProvider in the $policies array:
protected $policies = [
Job::class => JobPolicy::class
];
Then you can add the already existing middleware e.g.:
Routes::get('jobs/{job}/notes/{note}', ...)->middleware("can:view,job");
This will ensure that the currently authenticated user can view the job specified by the route job parameter.
There's more information in the documentation

I want to redirect users when they after login, to profile page

I want to redirect user to profile page when they log in. But, it directs the to home ('/') page. Sometimes, it works if I open it in incognito mode. but not every time.
Following is my Login controller
class LoginController extends Controller
{
use AuthenticatesUsers;
protected function redirectTo()
{
return '/profile';
}
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct(Request $request)
{
if($email = $request->user) {
$user = User::where('email', $email)->first();
if($user && $user->auto_login_key == $request->key) {
Auth::loginUsingId($user->id);
} else {
Redirect::to('/login')->send();
}
}
$this->middleware('guest')->except('logout');
}
}
And this is my Redirected authenticated miidleware
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 (Auth::guard($guard)->check()) {
return redirect('/profile');
}
return $next($request);
}
}
You can use return redirect('/profile'); inside your authentication function, for exmaple:
public function __construct(Request $request)
{
if($email = $request->user) {
$user = User::where('email', $email)->first();
if($user && $user->auto_login_key == $request->key) {
Auth::loginUsingId($user->id);
return redirect('/profile');
} else {
Redirect::to('/login')->send();
}
}
$this->middleware('guest')->except('logout');
}
Don't change anything, anywhere. In your LoginController, just change your $redirectTo variable to '/profile':
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/profile';
As it is working in incognito, the issue is just with cache. You can hard-reload (reload and clear cache) by pressing Ctrl + F5
AS i understand your problem, you have to first clear cache after that type of changes and make sure your browser cache is clear.
return redirect('/profile');

redirecTo() method in laravel not working

I have been trying to redirect a user after login, there are two links that should be redirected to when a certain condition is fulfilled.
protected function redirectTo(){
$userRole = User::findOrFail(Auth::id());
// dd($userRole->roles);
if($userRole->roles == 'admin'){
return 'admin/controlpanel';
}
elseif ($userRole->roles == 'participant') {
return 'student/profile';
}
}
I created this function to redirect but it still redirect to '/home'. Then I read over here and on git that I also had to the modify RedirectIfAuthenticated model in the middleware, I did this
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use App\User;
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 (Auth::guard($guard)->check()) {
return self::redirectTo();
}
return $next($request);
}
protected function redirectTo(){
$userRole = User::findOrFail(Auth::id());
if($userRole->roles == 'admin'){
return 'admin/controlpanel';
}
if ($userRole->roles == 'participant') {
return 'student/profile';
}
}
}
but is still keeps giving me this error in my previous question
here
I reverted to my previous git commit, then coded step by step till I discovered it was coming from the middleware I modified...
use redirect helper like this: return redirect('admin/controlpanel');

Error in Handler Class - Laravel

I am using Laravel 5.5 and trying to implement multi authentication for users and admin. I am getting this error when i try to call admin login form in browser.
Error :
Declaration of App\Exceptions\Handler::unauthenticated($request, App\Exceptions\AuthenticationException $exception) should be compatible with Illuminate\Foundation\Exceptions\Handler::unauthenticated($request, Illuminate\Auth\AuthenticationException $exception)
Here is my unauthenticated function in app/Exceptions/Handler:
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
$guard = array_get($exception->guards(), 0);
switch ($guard) {
case 'admin':
$login = 'admin.login';
break;
default:
$login = 'login';
break;
}
return redirect()->guest(route($login));
}
Please help me to resolve this issue.
You forgot to add use Illuminate\Auth\AuthenticationException at the top of your file
I am using Laravel 7.X
And I prefer to do that in Authenticate middleware
I did it like bellow and It is working well for me.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Support\Arr;
class Authenticate extends Middleware
{
protected $guards = [];
/**
* 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)
{
$this->guards = $guards;
return parent::handle($request, $next, ...$guards);
}
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* #param \Illuminate\Http\Request $request
* #return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
if (Arr::first($this->guards) === 'admin') {
return route('admin.login');
}
return route('trainee.login');
}
}
}
Thank you for your recent answer Thanh Nguyen. My custom auth middleware is work with the latest version
if (Arr::first($this->guards) === 'admin') {
return route('admin.login');
}
return route('customer.login');
Previously using unauthenticated function inside Handler.php to replace the parent function.
protected function unauthenticated($request, AuthenticationException $exception)
{
$guard = Arr::get($exception->guards(), 0);
switch ($guard) {
case 'respondent':
$login = 'respondents.login';
break;
case 'admin':
$login = 'admin.login';
break;
default:
$login = 'admin.login';
break;
}
return $request->expectsJson()
? response()->json(['message' => $exception->getMessage()], 401)
: redirect()->guest(route($login));
}
Both is working, but there was likely an issue for latest version on array_get to obtain guards we use:
$guard = array_get($exception->guards(), 0);
For anyone facing this issue, this method has been deprecated for Laravel 7.* and above
Error in Handler Class - Laravel
public function handle($request, Closure $next)
With
public function handle($request, Closure $next, ...$auth)

Categories